-
Notifications
You must be signed in to change notification settings - Fork 587
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make NIP-42 fallback a requirement to NIP-43
- Loading branch information
1 parent
fa6beee
commit 9ba1db1
Showing
7 changed files
with
254 additions
and
72 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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,107 @@ | ||
NIP-43 | ||
====== | ||
|
||
Fast Authentication | ||
------------------- | ||
|
||
`draft` `optional` `author:arthurfranca` | ||
|
||
This is a `client` to `relay` authentication procedure which is | ||
fast and easy to implement because it's non-interactive. | ||
|
||
Authentication happens on connection start, not | ||
requiring message exchange between `client` and `relay`. | ||
|
||
For `relays` implementing this NIP, it must be offered **in addition to** | ||
NIP-42 to maintain backward compatibility (follow [this section](#backward-compatibility)). | ||
|
||
## Motivation | ||
|
||
A relay may want to require clients to authenticate to access restricted resources. For example, | ||
|
||
- A relay may request payment or other forms of whitelisting to publish events. | ||
It may choose to accept events with any pubkey value as long as they are published from an authenticated user; | ||
- A relay may limit access to `kind: 4` DMs to only the parties involved in the chat exchange, | ||
and for that it may require authentication before clients can query for that kind. | ||
- A relay may limit subscriptions of any kind to paying users or users whitelisted through any other means, | ||
and require authentication. | ||
|
||
## How to Authenticate | ||
|
||
The `client` must generate a `kind: 22242` ephemeral event with the current time as `created_at` | ||
and the relay url as a `relay` tag. | ||
Then it has to stringify the JSON event and [percent-encode](https://www.rfc-editor.org/rfc/rfc3986#page-12) it. | ||
The resulting string is used as `authorization` query param when connecting to the relay. | ||
|
||
### Javascript Example | ||
|
||
```js | ||
const relayUrl = 'wss://relay.example.com' | ||
// add id and signature as usual | ||
const jsonEvent = generateNostrEvent({ | ||
pubkey: "...", | ||
created_at: Math.floor(Date.now() / 1000), | ||
kind: 22242, | ||
tags: [['relay', relayUrl]], | ||
content: "" | ||
}) | ||
const auth = window.encodeURIComponent(JSON.stringify(jsonEvent)) | ||
const ws = new WebSocket(`${relayUrl}?authorization=${auth}`) | ||
ws.addEventListener('open', () => console.log('auth accepted')) | ||
ws.addEventListener('close', () => console.log('disconnected') ) | ||
``` | ||
|
||
## Relay Handling | ||
|
||
`Relays` that require users to authenticate before performing atleast one action, must authenticate user on connection request. | ||
The authorization query param must be decoded and validated. A valid event must: | ||
- be of `kind` `22242`; | ||
- have `created_at` within a small time window relative to the current date (e.g. 60 seconds); | ||
- have the `relay` tag url value with the same domain name as the relay. | ||
|
||
If the event is valid, its `pubkey` identifies the authenticated user. | ||
|
||
If the user is not authorized to access the `relay`, instead of rejecting the connection right away, `relay` must fallback to NIP-42 following [this section](#backward-compatibility). | ||
|
||
The `relay` should send a `NOTICE` or `OK` message (as per [NIP-20](20.md)) with a standard prefix `"restricted: "` (readable both by humans and machines) | ||
when blocking authenticated user from accessing some resources. | ||
|
||
For example, if an already authenticated user A requests DMs not sent by him and meant to be read only by user B, | ||
relay should send a `NOTICE` like this one: | ||
|
||
``` | ||
["NOTICE", "restricted: not authorized to access this user's DMs, please login with NIP-43 or NIP-42"] | ||
``` | ||
|
||
## Security Measures | ||
|
||
The used protocol must be `wss` (WebSocket Secure). | ||
|
||
Although not required, the authorization event `id` should be stored by the `relay` for the same above mentioned time window so that | ||
if the same event `id` is used twice, the `relay` should reject the connection immediately and | ||
should also disconnect the user that first used the event to authenticate. | ||
In this case the `relay` may send a `NOTICE` message with `"restricted: "` prefix informing | ||
the first user before disconnecting him, for example: | ||
|
||
``` | ||
["NOTICE", "restricted: your client is misbehaving, authorization event can't be reused."] | ||
``` | ||
|
||
## Backward Compatibility | ||
|
||
It is crucial that `relays` offer NIP-42 as a fallback mechanism for `clients` that don't intend implementing NIP-43. | ||
|
||
If the `authorization` query param is **absent**, the `relay` should send to connecting `clients`, | ||
at any moment (for example, upon connection establishment), an `AUTH` message containing a `challenge`, in accordance with NIP-42, as follows: | ||
|
||
``` | ||
["AUTH", <challenge-string>] | ||
``` | ||
|
||
`Clients` are then expected to reply with an `AUTH` message containg a `kind` `22242` event, similar to the above mentioned one, **with** the same challenge as a tag, for example: | ||
|
||
``` | ||
["AUTH", { "kind": 22242, ..., "tags": [["relay", "wss://relay.example.com/"], ["challenge", "challengestringhere"]] }] | ||
``` | ||
|
||
`Relays` should validate the event as mentioned above, additionally checking if the `challenge` match the previously sent one. |
This file contains 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
This file contains 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