Integration with Nostr Login #14530

Open
opened 2025-11-02 11:15:24 -06:00 by GiteaMirror · 9 comments
Owner

Originally created by @Zig-VS-TypeScript-VS on GitHub (May 29, 2025).

Feature Description

Overview

We're requesting Gitea Issues to add support for the Nostr protocol for login. This would enable users to securely and privately log into Gitea using their Nostr key pair, leveraging the benefits of Nostr's decentralized authentication.

Why Nostr NIP Login?

  • Decentralized Identity:
    Users wouldn't rely on centralized identity providers (like GitHub or Google). Their identity would be controlled by their own Nostr key pair.

  • Privacy Protection:
    Users wouldn't need to expose personal identifying information (like email addresses or phone numbers) during login. Authentication would occur solely via their public key.

  • Censorship Resistance:
    Nostr's decentralized nature makes it more resistant to censorship, meaning user identities are less likely to be easily blocked or deleted.

  • Unified Identity:
    Users could use the same Nostr identity to log in and interact with various Nostr-enabled applications and services.

  • Simplified Process:
    For users who already have a Nostr key, the login process would be much more convenient, eliminating the need to register new accounts or remember extra passwords.

Feature Description

Login Option

  • Add a "Log in with Nostr" option to the Gitea login page.

Nostr Key Pair Verification

  1. Initiate Login:
    When a user clicks "Log in with Nostr," Gitea would generate a random, time-sensitive challenge.

  2. Challenge Delivery:
    Gitea sends this challenge to the user's Nostr client (via a NIP-07 browser extension, mobile app, or desktop application).

  3. User Action:
    The user will sign the challenge within their Nostr client using their private key.

  4. Response:
    The signed message is returned to the Gitea server.

  5. Verification:
    The Gitea server verifies the signature's validity using the user's Nostr public key.

  6. Successful Login:
    Upon successful verification, the user is logged into Gitea.

User Association

  • First-time Login:

    • Offer an option to link the user's Nostr public key to an existing Gitea account or to create a new one.
  • Account Creation:

    • If a new account is created, Gitea could use the user's Nostr public key as their unique identifier and offer the option to set a Gitea username.
  • Multiple Nostr Public Key Association:

    • Allow users to link multiple Nostr public keys to the same Gitea account to handle scenarios such as lost or rotated keys.
  • Display Public Key:

    • Show the user's Nostr public key on their Gitea profile page for easy following or verification by other users.
  • Optional Nostr NIP-05 Verification:

    • Support NIP-05 (which allows users to verify their Nostr public key's association with a specific domain via DNS records) to increase identity reliability.
    • Display the NIP-05 verification status on the user's profile.
  • Secure Logout:

    • Ensure that standard Gitea session management and logout procedures are compatible with the Nostr login flow.

Security and Privacy Features

  • No Password Storage:

    • The Gitea server doesn't need to store user passwords, reducing the risk of data breaches.
  • User-Controlled Keys:

    • The user's Nostr private key remains on their device or client; Gitea never gains access to it.
  • Challenge-Response Mechanism:

    • Every login uses a unique, time-sensitive challenge, preventing replay attacks.
  • No PII Disclosure:

    • Gitea only receives and verifies the user's Nostr public key and signature; it does not acquire personal data like email addresses or phone numbers.
  • Privacy-Preserving Public Identity:

    • The Nostr public key is pseudonymous unless the user links it to a specific identity (e.g., via NIP-05 or by making it public on their profile).
  • Protection Against Identity Theft:

    • Even if the Gitea server is compromised, attackers cannot impersonate users without access to their private keys.
  • Decentralized Auditability:

    • The transparency of the Nostr protocol allows community auditing, fostering trust in the system.
  • Future Extensibility:

    • This design, being compatible with Nostr NIPs, lays the groundwork for future integrations (e.g., Nostr publishing for issue updates or comments).
  • Granular Permissions:

    • Gitea may manage permissions for Nostr-logged-in users through its standard permissions system, integrating them seamlessly into existing user management processes.

Implementation Considerations

  • NIP-07 Browser Extension Integration:

    • Prioritize integration with the most common Nostr login method.
  • User Experience:

    • Ensure the login process is clear and straightforward, even for users new to Nostr.
  • Error Handling:

    • Provide clear error messages to help users resolve login issues.
  • Compatibility:

    • Ensure that the Nostr login method works alongside existing Gitea account systems, permission management, and audit logs.
  • Documentation:

    • Furnish detailed documentation for configuring and using the Nostr login feature.

Expected Benefits

  • Enhance Gitea's security and privacy protection.
  • Attract users who value decentralization and privacy.
  • Strengthen Gitea's reputation as an open and free software platform.
  • Promote the development and adoption of the Nostr ecosystem.

We believe integrating Nostr NIP login would be a significant step toward making Gitea even more secure, private, and decentralized.

Screenshots

No response

Originally created by @Zig-VS-TypeScript-VS on GitHub (May 29, 2025). ### Feature Description ## Overview We're requesting Gitea Issues to add support for the [Nostr protocol](https://github.com/nostr-protocol/nostr) for login. This would enable users to securely and privately log into Gitea using their Nostr key pair, leveraging the benefits of Nostr's decentralized authentication. ## Why [Nostr NIP](https://github.com/nostr-protocol/nips) Login? - **Decentralized Identity:** Users wouldn't rely on centralized identity providers (like GitHub or Google). Their identity would be controlled by their own Nostr key pair. - **Privacy Protection:** Users wouldn't need to expose personal identifying information (like email addresses or phone numbers) during login. Authentication would occur solely via their public key. - **Censorship Resistance:** Nostr's decentralized nature makes it more resistant to censorship, meaning user identities are less likely to be easily blocked or deleted. - **Unified Identity:** Users could use the same Nostr identity to log in and interact with various Nostr-enabled applications and services. - **Simplified Process:** For users who already have a Nostr key, the login process would be much more convenient, eliminating the need to register new accounts or remember extra passwords. ## Feature Description ### Login Option - Add a **"Log in with Nostr"** option to the Gitea login page. ### Nostr Key Pair Verification 1. **Initiate Login:** When a user clicks **"Log in with Nostr,"** Gitea would generate a random, time-sensitive challenge. 2. **Challenge Delivery:** Gitea sends this challenge to the user's Nostr client (via a [NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md) browser extension, mobile app, or desktop application). 3. **User Action:** The user will sign the challenge within their Nostr client using their private key. 4. **Response:** The signed message is returned to the Gitea server. 5. **Verification:** The Gitea server verifies the signature's validity using the user's Nostr public key. 6. **Successful Login:** Upon successful verification, the user is logged into Gitea. ### User Association - **First-time Login:** - Offer an option to link the user's Nostr public key to an existing Gitea account or to create a new one. - **Account Creation:** - If a new account is created, Gitea could use the user's Nostr public key as their unique identifier and offer the option to set a Gitea username. - **Multiple Nostr Public Key Association:** - Allow users to link multiple Nostr public keys to the same Gitea account to handle scenarios such as lost or rotated keys. - **Display Public Key:** - Show the user's Nostr public key on their Gitea profile page for easy following or verification by other users. - **Optional Nostr NIP-05 Verification:** - Support NIP-05 (which allows users to verify their Nostr public key's association with a specific domain via DNS records) to increase identity reliability. - Display the NIP-05 verification status on the user's profile. - **Secure Logout:** - Ensure that standard Gitea session management and logout procedures are compatible with the Nostr login flow. ## Security and Privacy Features - **No Password Storage:** - The Gitea server doesn't need to store user passwords, reducing the risk of data breaches. - **User-Controlled Keys:** - The user's Nostr private key remains on their device or client; Gitea never gains access to it. - **Challenge-Response Mechanism:** - Every login uses a unique, time-sensitive challenge, preventing replay attacks. - **No PII Disclosure:** - Gitea only receives and verifies the user's Nostr public key and signature; it does not acquire personal data like email addresses or phone numbers. - **Privacy-Preserving Public Identity:** - The Nostr public key is pseudonymous unless the user links it to a specific identity (e.g., via NIP-05 or by making it public on their profile). - **Protection Against Identity Theft:** - Even if the Gitea server is compromised, attackers cannot impersonate users without access to their private keys. - **Decentralized Auditability:** - The transparency of the Nostr protocol allows community auditing, fostering trust in the system. - **Future Extensibility:** - This design, being compatible with Nostr NIPs, lays the groundwork for future integrations (e.g., Nostr publishing for issue updates or comments). - **Granular Permissions:** - Gitea may manage permissions for Nostr-logged-in users through its standard permissions system, integrating them seamlessly into existing user management processes. ## Implementation Considerations - **[NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md) Browser Extension Integration:** - Prioritize integration with the most common Nostr login method. - **User Experience:** - Ensure the login process is clear and straightforward, even for users new to Nostr. - **Error Handling:** - Provide clear error messages to help users resolve login issues. - **Compatibility:** - Ensure that the Nostr login method works alongside existing Gitea account systems, permission management, and audit logs. - **Documentation:** - Furnish detailed documentation for configuring and using the Nostr login feature. ## Expected Benefits - Enhance Gitea's security and privacy protection. - Attract users who value decentralization and privacy. - Strengthen Gitea's reputation as an open and free software platform. - Promote the development and adoption of the Nostr ecosystem. --- We believe integrating Nostr NIP login would be a significant step toward making Gitea even more secure, private, and decentralized. ### Screenshots _No response_
GiteaMirror added the type/proposal label 2025-11-02 11:15:24 -06:00
Author
Owner

@techknowlogick commented on GitHub (May 29, 2025):

I'm not so familiar with this protocol, are you aware of any existing libraries that we could use, or even better perhaps an OIDC bridge as that's an existing standard we support?

@techknowlogick commented on GitHub (May 29, 2025): I'm not so familiar with this protocol, are you aware of any existing libraries that we could use, or even better perhaps an OIDC bridge as that's an existing standard we support?
Author
Owner

@raucao commented on GitHub (May 31, 2025):

Nostr is based on serverless identity with nothing but public/private keypairs, so OIDC doesn't make sense for it.

There's a well-maintained Go library, which is also used by the original creator of the Nostr protocol: https://github.com/nbd-wtf/go-nostr

For website logins, you can ignore most of the protocol really. The only things needed are:

  1. The user's pubkey (32 bytes hex), which can also be acquired from a NIP-07-compatible extension, as mentioned above (so users don't have to copy and paste keys around).
  2. A Nostr event that can be signed by the user via the extension and sent to the server for verification and login.

When relying solely on NIP-07 extensions, you can also just hide the Nostr login option if no extension is detected on the login page, so it's not confusing for any other users.

Example

Here's a simple implementation I did for an accounts management web app, based on Ruby on Rails and Stimulus JS (which is almost vanilla JS), which should be understandable for anyone wanting to implement it:

The event I'm using is a kind 22242, but with a site tag instead of a relay one. It's defined in NIP-42, the rest of which is also irrelevant for this use case.

Integration with LDAP

As a bonus, and since I was just fixing a bug with Gitea's LDAP sync before I stumbled upon this issue: if the Nostr key is stored in an LDAP directory, which is the case for our accounts, then Gitea could also make use of that and import the pubkeys from there if configured by the admin. Here's our LDIF for the attribute schema (complete with a registered PEN), which anyone can use for storing Nostr pubkeys in their directories:

dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 1.3.6.1.4.1.61554.1.1.2.1.21
  NAME 'nostrKey'
  DESC 'Nostr public key'
  EQUALITY caseExactIA5Match
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
  SINGLE-VALUE )
@raucao commented on GitHub (May 31, 2025): Nostr is based on serverless identity with nothing but public/private keypairs, so OIDC doesn't make sense for it. There's a well-maintained Go library, which is also used by the original creator of the Nostr protocol: https://github.com/nbd-wtf/go-nostr For website logins, you can ignore most of the protocol really. The only things needed are: 1. The user's pubkey (32 bytes hex), which can also be acquired from a [NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md)-compatible extension, as mentioned above (so users don't have to copy and paste keys around). 2. A Nostr event that can be signed by the user via the extension and sent to the server for verification and login. When relying solely on NIP-07 extensions, you can also just hide the Nostr login option if no extension is detected on the login page, so it's not confusing for any other users. ### Example Here's a simple implementation I did for an accounts management web app, based on Ruby on Rails and Stimulus JS (which is almost vanilla JS), which should be understandable for anyone wanting to implement it: * [Client-side JS](https://gitea.kosmos.org/kosmos/akkounts/src/branch/master/app/javascript/controllers/nostr_login_controller.js) * [Server route/action](https://gitea.kosmos.org/kosmos/akkounts/src/branch/master/app/controllers/users/sessions_controller.rb#L22-L49) The event I'm using is a kind 22242, but with a `site` tag instead of a `relay` one. It's defined in [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md), the rest of which is also irrelevant for this use case. ### Integration with LDAP As a bonus, and since I was just fixing a bug with Gitea's LDAP sync before I stumbled upon this issue: if the Nostr key is stored in an LDAP directory, which is the case for our accounts, then Gitea could also make use of that and import the pubkeys from there if configured by the admin. Here's our LDIF for the attribute schema (complete with a registered PEN), which anyone can use for storing Nostr pubkeys in their directories: ```ldif dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( 1.3.6.1.4.1.61554.1.1.2.1.21 NAME 'nostrKey' DESC 'Nostr public key' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) ```
Author
Owner

@dadofsambonzuki commented on GitHub (Jul 30, 2025):

NIP-98 defines HTTP Auth, which is what most clients use for 'Login with Nostr'.

If implemented, admins would simply have to add the Nostr pubkey (npub) to the user or users could 'sign-up with nostr' and only share their npub.

NIP-98 compatible browser extensions handle the signing of the ephemeral challenge with the users private key (nsec).

@dadofsambonzuki commented on GitHub (Jul 30, 2025): [NIP-98](https://nostrhub.io/98) defines HTTP Auth, which is what most clients use for 'Login with Nostr'. If implemented, admins would simply have to add the Nostr pubkey (npub) to the user or users could 'sign-up with nostr' and only share their npub. NIP-98 compatible browser extensions handle the signing of the ephemeral challenge with the users private key (nsec).
Author
Owner

@raucao commented on GitHub (Jul 30, 2025):

As far as I understand NIP-98 is for signing every single request, which is unnecessary when you can just log in and then have a normal Gitea login session. Did you have a look at my example above? It works like a charm with browser extensions, and they also show the correct wording/content when connecting a key or logging in.

@raucao commented on GitHub (Jul 30, 2025): As far as I understand NIP-98 is for signing every single request, which is unnecessary when you can just log in and then have a normal Gitea login session. Did you have a look at my example above? It works like a charm with browser extensions, and they also show the correct wording/content when connecting a key or logging in.
Author
Owner

@dadofsambonzuki commented on GitHub (Aug 6, 2025):

NIP-98 is really just a more robust way to get a signed event specifically for auth purposes. You'd use the NIP-07 approach, but the event inside would be a NIP-98 kind. Gives better, more timely guarantees to the server.

You don't do this on each request, once you auth gitea would handle that lifecycle in the session using whatever mechanisms it currently uses for that.

@dadofsambonzuki commented on GitHub (Aug 6, 2025): NIP-98 is really just a more robust way to get a signed event specifically for auth purposes. You'd use the NIP-07 approach, but the event inside would be a NIP-98 kind. Gives better, more timely guarantees to the server. You don't do this on each request, once you auth gitea would handle that lifecycle in the session using whatever mechanisms it currently uses for that.
Author
Owner

@raucao commented on GitHub (Aug 7, 2025):

Gives better, more timely guarantees to the server.

How so? If there's any benefit over kind 22242 events, then I'd be interested in what it is. "Better, more timely guarantees" is not possible, since it's already requiring to sign a challenge and restricting created_at times.

@raucao commented on GitHub (Aug 7, 2025): > Gives better, more timely guarantees to the server. How so? If there's any benefit over kind 22242 events, then I'd be interested in what it is. "Better, more timely guarantees" is not possible, since it's already [requiring to sign a challenge and restricting `created_at` times](https://github.com/nostr-protocol/nips/blob/master/42.md#signed-event-verification).
Author
Owner

@dadofsambonzuki commented on GitHub (Aug 7, 2025):

kind 22242 is specifically for nostr relay auth and is done over websockets. Nostr-native if you will.

NIP-98 requires target URL and timestamp within a 'reasonable' (60s) time and so is more tightly scoped.

It's what most services I know of use.

@dadofsambonzuki commented on GitHub (Aug 7, 2025): kind 22242 is specifically for nostr relay auth and is done over websockets. Nostr-native if you will. NIP-98 requires target URL and timestamp within a 'reasonable' (60s) time and so is more tightly scoped. It's what most services I know of use.
Author
Owner

@raucao commented on GitHub (Aug 7, 2025):

We're using a site tag instead of relay, with the domain of the site to log in to. There's no need to specify an exact URL on the domain, because the log in is valid for the entire domain, regardless of URL.

NIP-98 requires a target URL and HTTP verb, but no challenge. Our approach uses a kind that was designed for one-time authentication, whereas NIP-98 was designed for repeated inline authorization.

Thus, both approaches, when used for logging in to a website that then provides its own session, are using the underlying NIPs in a way that they weren't intended for originally. Mine does authentication for sites instead of relays (but both are just domains), while yours does inline authorization on a specific URL for user authentication to a whole site.

Personally, I prefer both the DX and UX of my approach, but if the signing UX is equally good with yours (which I haven't looked into), then I think either one is OK to implement.

@raucao commented on GitHub (Aug 7, 2025): We're using a `site` tag instead of `relay`, with the domain of the site to log in to. There's no need to specify an exact URL on the domain, because the log in is valid for the entire domain, regardless of URL. NIP-98 requires a target URL and HTTP verb, but no challenge. Our approach uses a kind that was designed for one-time **authentication**, whereas NIP-98 was designed for repeated inline **authorization**. Thus, both approaches, when used for logging in to a website that then provides its own session, are using the underlying NIPs in a way that they weren't intended for originally. Mine does authentication for sites instead of relays (but both are just domains), while yours does inline authorization on a specific URL for user authentication to a whole site. Personally, I prefer both the DX and UX of my approach, but if the signing UX is equally good with yours (which I haven't looked into), then I think either one is OK to implement.
Author
Owner

@dadofsambonzuki commented on GitHub (Aug 7, 2025):

Agreed.

As long as an event is signed and presented then it doesn't really matter how.

@dadofsambonzuki commented on GitHub (Aug 7, 2025): Agreed. As long as an event is signed and presented then it doesn't *really* matter how.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#14530