-
Notifications
You must be signed in to change notification settings - Fork 736
Nostr Web Tokens #2187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pippellia-btc
wants to merge
2
commits into
nostr-protocol:master
Choose a base branch
from
pippellia-btc:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Nostr Web Tokens #2187
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| # NIP WT. Nostr Web Tokens | ||
|
|
||
| `draft` `optional` | ||
|
|
||
| ## Overview | ||
|
|
||
| A Nostr Web Token (NWT) is a signed Nostr event used to convey signed claims between parties on the web. | ||
|
|
||
| Claims are pieces of information asserted about a subject. A claim is identified by a name, and associated with one or more values. | ||
|
|
||
| A NWT is not a JSON Web Token (JWT), but adopts its semantics where applicable. | ||
|
|
||
| ## Event | ||
|
|
||
| A NWT has a `kind 27519`, in reference to [REC-7519](https://datatracker.ietf.org/doc/html/rfc7519) that defines the JWT. | ||
|
|
||
| Claims are represented as `tags`, following JWT naming conventions and semantics where applicable. Claims that allow a single value MUST appear only once; claims that allow multiple values are represented by repeated tags. | ||
|
|
||
| ### Example | ||
|
|
||
| ```jsonc | ||
| { | ||
| "id": <32-bytes hex-encoded sha256>, | ||
| "pubkey": <32-bytes hex-encoded public key>, | ||
| "created_at": <unix timestamp in seconds>, | ||
| "kind": 27519, | ||
| "tags": [ | ||
| ["aud", "blossom.example.com"], | ||
| ["aud", "cdn.another.com"], | ||
| ["aud", "cdn.last.one"], | ||
| ["exp", "1710003600"], | ||
| ["nbf", "1710000000"], | ||
| ["action", "upload"], // custom claim | ||
| ["payload", "b1674191a...dsad"] // custom claim | ||
| ], | ||
| "content": "upload bitcoin.pdf", | ||
| "sig": <64-bytes hex-encoded signature> | ||
| } | ||
| ``` | ||
|
|
||
| ### Registered Claims | ||
|
|
||
| | Claim | Tag | Status | Type | Cardinality | | ||
| |-----------|--------|------------|------ | --------------------| | ||
| | Issuer | `iss` | Optional | string | single | | ||
| | Subject | `sub` | Optional | string | single | | ||
| | Audience | `aud` | Recommended | string | multi | | ||
| | Issued At | `iat` | Optional | stringified timestamp* | single | | ||
| | Expiration | `exp` | Recommended | stringified timestamp* | single | | ||
| | Not Before | `nbf` | Optional | stringified timestamp* | single | | ||
|
|
||
| \* Timestamp values MUST be base-10 non-negative integer seconds since the Unix epoch. Verifiers SHOULD allow a small clock skew (e.g. ±60 seconds). | ||
|
|
||
| #### Issuer `iss` | ||
|
|
||
| The `iss` (issuer) claim identifies the entity that issued the | ||
| NWT. | ||
| This tag is OPTIONAL. If not present, the issuer of the NWT is assumed to be the Nostr public key (`pubkey`) that signed the event. | ||
|
|
||
| #### Subject `sub` | ||
|
|
||
| The `sub` (subject) claim identifies the entity that is the subject of the NWT. | ||
| This tag is OPTIONAL. If not present, the subject of the NWT is assumed to be the Nostr public key (`pubkey`) that signed the event. | ||
|
|
||
| #### Audience `aud` | ||
|
|
||
| The `aud` (audience) claim identifies the recipients that the NWT is | ||
| intended for. | ||
| Recipients MAY be of various types, such as pubkeys, domain names or even specific endpoints. A verifier MUST reject a NWT if it doesn't identify itself with a value in the audience claim. The interpretation of "identify itself" is application-specific. | ||
| This tag is OPTIONAL, but recommended. If not present, the audience of the NWT is assumed to be everyone, which may cause [security issues](#security-considerations). | ||
|
|
||
| #### Issued At `iat` | ||
|
|
||
| The `iat` (issued at) claim identifies the time at which the NWT was | ||
| issued. | ||
| This tag is OPTIONAL. If not present, the issued timestamp is assumed to be the timestamp of the Nostr event (`created_at`). If present, verifiers MUST use `iat` instead of `created_at`. | ||
|
|
||
| #### Expiration `exp` | ||
|
|
||
| The `exp` (expiration) claim identifies the expiration time on | ||
| or after which the NWT MUST NOT be accepted for processing. | ||
| This tag is OPTIONAL, but recommended. If not present, the expiration is assumed to never occur, which may cause [security issues](#security-considerations). | ||
|
|
||
| #### Not Before `nbf` | ||
|
|
||
| The `nbf` (not before) claim identifies the time before which the NWT | ||
| MUST NOT be accepted for processing. | ||
| This tag is OPTIONAL. | ||
|
|
||
| ### Additional Claims | ||
|
|
||
| A producer and consumer of a NWT MAY agree to use additional claims (e.g. `roles`, `scope` etc.). These additional claims MUST be encoded as `tags`, however, their definition and intended use is application specific and is not defined here. | ||
|
|
||
|
|
||
| ### Content | ||
|
|
||
| The `content` field SHOULD contain a human readable message intended to be displayed to the signer of the NWT, explaining its intended use. For example, `authorize deletion of fiat.pdf`. | ||
|
|
||
|
|
||
| ## Validation Rules | ||
|
|
||
| A verifier MUST: | ||
|
|
||
| 1. Verify the Nostr event id. | ||
| 2. Verify the Nostr event signature. | ||
| 3. Verify the event `kind` is `27519` | ||
| 4. Enforce `exp`, `nbf`, and `aud` claims when present; apply default behaviors when absent. | ||
| 5. Validate issuer trust (application-defined) | ||
|
|
||
|
|
||
| ## Transport Encoding | ||
|
|
||
| A NWT MAY be transported using any non-destructive encoding. | ||
| Its primary use, however, is transmission via an HTTP `Authorization` header using the `Nostr` scheme, where the token is encoded using `Base64URL` (URL-safe base 64) without padding. | ||
|
|
||
| Example: | ||
|
|
||
| ``` | ||
| Authorization: Nostr <base64url-no-padding-token> | ||
| ``` | ||
|
|
||
|
|
||
| ## Security Considerations | ||
|
|
||
| NWTs are primarily intended for authentication and/or authorization purposes. Just like JWTs, they are bearer tokens; if a malicious actor is able to get a NWT, it may use it to impersonate the user. | ||
|
|
||
| Because of that, it is recommended to: | ||
|
|
||
| * Use short expiration times (e.g. 5 minutes) | ||
| * Restrict the audience for destructive operations to avoid [replay attacks](https://en.wikipedia.org/wiki/Replay_attack) | ||
| * Use the NWT event `id` if replay detection if needed | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then what about HTTP Auth? Can't it do the same job>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean NIP-98? No it can't do the same job, not without requiring a lot of signatures.
Comparison here: https://github.com/pippellia-btc/nostr-web-tokens?tab=readme-ov-file#comparisons