mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-22 08:25:53 -05:00
CLOSED
messages for relays that want to reject REQs and NIP-42 AUTH
integration (#902)
Co-authored-by: monlovesmango <96307647+monlovesmango@users.noreply.github.com>
This commit is contained in:
parent
c07f0eab1a
commit
2bd4bf7841
12
01.md
12
01.md
|
@ -141,19 +141,25 @@ Relays can send 4 types of messages, which must also be JSON arrays, according t
|
||||||
* `["EVENT", <subscription_id>, <event JSON as defined above>]`, used to send events requested by clients.
|
* `["EVENT", <subscription_id>, <event JSON as defined above>]`, used to send events requested by clients.
|
||||||
* `["OK", <event_id>, <true|false>, <message>]`, used to indicate acceptance or denial of an `EVENT` message.
|
* `["OK", <event_id>, <true|false>, <message>]`, used to indicate acceptance or denial of an `EVENT` message.
|
||||||
* `["EOSE", <subscription_id>]`, used to indicate the _end of stored events_ and the beginning of events newly received in real-time.
|
* `["EOSE", <subscription_id>]`, used to indicate the _end of stored events_ and the beginning of events newly received in real-time.
|
||||||
|
* `["CLOSED", <subscription_id>, <message>]`, used to indicate that a subscription was ended on the server side.
|
||||||
* `["NOTICE", <message>]`, used to send human-readable error messages or other things to clients.
|
* `["NOTICE", <message>]`, used to send human-readable error messages or other things to clients.
|
||||||
|
|
||||||
This NIP defines no rules for how `NOTICE` messages should be sent or treated.
|
This NIP defines no rules for how `NOTICE` messages should be sent or treated.
|
||||||
|
|
||||||
- `EVENT` messages MUST be sent only with a subscription ID related to a subscription previously initiated by the client (using the `REQ` message above).
|
- `EVENT` messages MUST be sent only with a subscription ID related to a subscription previously initiated by the client (using the `REQ` message above).
|
||||||
- `OK` messages MUST be sent in response to `EVENT` messages received from clients, they must have the 3rd parameter set to `true` when an event has been accepted by the relay, `false` otherwise. The 4th parameter MUST always be present, but MAY be an empty string when the 3rd is `true`, otherwise it MUST be a string formed by a machine-readable single-word prefix followed by a `:` and then a human-readable message. The standardized machine-readable prefixes are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, and `error` for when none of that fits. Some examples:
|
- `OK` messages MUST be sent in response to `EVENT` messages received from clients, they must have the 3rd parameter set to `true` when an event has been accepted by the relay, `false` otherwise. The 4th parameter MUST always be present, but MAY be an empty string when the 3rd is `true`, otherwise it MUST be a string formed by a machine-readable single-word prefix followed by a `:` and then a human-readable message. Some examples:
|
||||||
|
|
||||||
* `["OK", "b1a649ebe8...", true, ""]`
|
* `["OK", "b1a649ebe8...", true, ""]`
|
||||||
* `["OK", "b1a649ebe8...", true, "pow: difficulty 25>=24"]`
|
* `["OK", "b1a649ebe8...", true, "pow: difficulty 25>=24"]`
|
||||||
* `["OK", "b1a649ebe8...", true, "duplicate: already have this event"]`
|
* `["OK", "b1a649ebe8...", true, "duplicate: already have this event"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]`
|
* `["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]`
|
* `["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]`
|
* `["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time. Is your system clock in sync?"]`
|
* `["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]`
|
* `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]`
|
* `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]`
|
||||||
|
- `CLOSED` messages MUST be sent in response to a `REQ` when the relay refuses to fulfill it. It can also be sent when a relay decides to kill a subscription on its side before a client has disconnected or sent a `CLOSE`. This message uses the same pattern of `OK` messages with the machine-readable prefix and human-readable message. Some examples:
|
||||||
|
* `["CLOSED", "sub1", "duplicate: sub1 already opened"]`
|
||||||
|
* `["CLOSED", "sub1", "unsupported: filter contains unknown elements"]`
|
||||||
|
* `["CLOSED", "sub1", "error: could not connect to the database"]`
|
||||||
|
* `["CLOSED", "sub1", "error: shutting down idle subscription"]`
|
||||||
|
- The standardized machine-readable prefixes for `OK` and `CLOSED` are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, and `error` for when none of that fits.
|
||||||
|
|
69
42.md
69
42.md
|
@ -12,17 +12,15 @@ This NIP defines a way for clients to authenticate to relays by signing an ephem
|
||||||
|
|
||||||
A relay may want to require clients to authenticate to access restricted resources. For example,
|
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 -- this can naïvely be achieved by limiting publication
|
- A relay may request payment or other forms of whitelisting to publish events -- this can naïvely be achieved by limiting publication to events signed by the whitelisted key, but with this NIP they may choose to accept any events as long as they are published from an authenticated user;
|
||||||
to events signed by the whitelisted key, but with this NIP they may choose to accept any events as long as they are published from an
|
- 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.
|
||||||
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.
|
- A relay may limit subscriptions of any kind to paying users or users whitelisted through any other means, and require authentication.
|
||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
|
|
||||||
This NIP defines a new message, `AUTH`, which relays can send when they support authentication and clients can send to relays when they want
|
### New client-relay protocol messages
|
||||||
to authenticate. When sent by relays, the message is of the following form:
|
|
||||||
|
This NIP defines a new message, `AUTH`, which relays can send when they support authentication and clients can send to relays when they want to authenticate. When sent by relays, the message is of the following form:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
["AUTH", <challenge-string>]
|
["AUTH", <challenge-string>]
|
||||||
|
@ -34,10 +32,11 @@ And, when sent by clients, of the following form:
|
||||||
["AUTH", <signed-event-json>]
|
["AUTH", <signed-event-json>]
|
||||||
```
|
```
|
||||||
|
|
||||||
The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and it should have at least two tags,
|
`AUTH` messages sent by clients should be answered with an `OK` message, like any `EVENT` message.
|
||||||
one for the relay URL and one for the challenge string as received from the relay.
|
|
||||||
Relays MUST exclude `kind: 22242` events from being broadcasted to any client.
|
### Canonical authentication event
|
||||||
`created_at` should be the current time. Example:
|
|
||||||
|
The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and it should have at least two tags, one for the relay URL and one for the challenge string as received from the relay. Relays MUST exclude `kind: 22242` events from being broadcasted to any client. `created_at` should be the current time. Example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -50,27 +49,49 @@ Relays MUST exclude `kind: 22242` events from being broadcasted to any client.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `OK` and `CLOSED` machine-readable prefixes
|
||||||
|
|
||||||
|
This NIP defines two new prefixes that can be used in `OK` (in response to event writes by clients) and `CLOSED` (in response to rejected subscriptions by clients):
|
||||||
|
|
||||||
|
- `"auth-required: "` - for when a client has not performed `AUTH` and the relay requires that to fulfill the query or write the event.
|
||||||
|
- `"restricted: "` - for when a client has already performed `AUTH` but the key used to perform it is still not allowed by the relay or is exceeding its authorization.
|
||||||
|
|
||||||
## Protocol flow
|
## Protocol flow
|
||||||
|
|
||||||
At any moment the relay may send an `AUTH` message to the client containing a challenge. After receiving that the client may decide to
|
At any moment the relay may send an `AUTH` message to the client containing a challenge. The challenge is valid for the duration of the connection or until another challenge is sent by the relay. The client MAY decide to send its `AUTH` event at any point and the authenticated session is valid afterwards for the duration of the connection.
|
||||||
authenticate itself or not. The challenge is expected to be valid for the duration of the connection or until a next challenge is sent by
|
|
||||||
the relay.
|
|
||||||
|
|
||||||
The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right
|
### `auth-required` in response to a `REQ` message
|
||||||
before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best. The authentication
|
|
||||||
is expected to last for the duration of the WebSocket connection.
|
|
||||||
|
|
||||||
Upon receiving a message from an unauthenticated user it can't fulfill without authentication, a relay may choose to notify the client. For
|
Given that a relay is likely to require clients to perform authentication only for certain jobs, like answering a `REQ` or accepting an `EVENT` write, these are some expected common flows:
|
||||||
that it can use a `NOTICE` or `OK` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example:
|
|
||||||
|
|
||||||
```json
|
```
|
||||||
["NOTICE", "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?"]
|
relay: ["AUTH", "<challenge>"]
|
||||||
|
client: ["REQ", "sub_1", {"kinds": [4]}]
|
||||||
|
relay: ["CLOSED", "sub_1", "auth-required: we can't serve DMs to unauthenticated users"]
|
||||||
|
client: ["AUTH", {"id": "abcdef...", ...}]
|
||||||
|
relay: ["OK", "abcdef...", true, ""]
|
||||||
|
client: ["REQ", "sub_1", {"kinds": [4]}]
|
||||||
|
relay: ["EVENT", "sub_1", {...}]
|
||||||
|
relay: ["EVENT", "sub_1", {...}]
|
||||||
|
relay: ["EVENT", "sub_1", {...}]
|
||||||
|
relay: ["EVENT", "sub_1", {...}]
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
or it can return an `OK` message noting the reason an event was not written using the same prefix:
|
In this case, the `AUTH` message from the relay could be sent right as the client connects or it can be sent immediately before the `CLOSED` is sent. The only requirement is that _the client must have a stored challenge associated with that relay_ so it can act upon that in response to the `auth-required` `CLOSED` message.
|
||||||
|
|
||||||
```json
|
### `auth-required` in response to an `EVENT` message
|
||||||
["OK", <event-id>, false, "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"]
|
|
||||||
|
The same flow is valid for when a client wants to write an `EVENT` to the relay, except now the relay sends back an `OK` message instead of a `CLOSED` message:
|
||||||
|
|
||||||
|
```
|
||||||
|
relay: ["AUTH", "<challenge>"]
|
||||||
|
client: ["EVENT", {"id": "012345...", ...}]
|
||||||
|
relay: ["OK", "012345...", false, "auth-required: we only accept events from registered users"]
|
||||||
|
client: ["AUTH", {"id": "abcdef...", ...}]
|
||||||
|
relay: ["OK", "abcdef...", true, ""]
|
||||||
|
client: ["EVENT", {"id": "012345...", ...}]
|
||||||
|
relay: ["OK", "012345...", true, ""]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Signed Event Verification
|
## Signed Event Verification
|
||||||
|
|
11
45.md
11
45.md
|
@ -27,7 +27,9 @@ In case a relay uses probabilistic counts, it MAY indicate it in the response wi
|
||||||
["COUNT", <subscription_id>, {"count": <integer>}]
|
["COUNT", <subscription_id>, {"count": <integer>}]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples:
|
Whenever the relay decides to refuse to fulfill the `COUNT` request, it MUST return a `CLOSED` message.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### Followers count
|
### Followers count
|
||||||
|
|
||||||
|
@ -49,3 +51,10 @@ In case a relay uses probabilistic counts, it MAY indicate it in the response wi
|
||||||
["COUNT", <subscription_id>, {"kinds": [1]}]
|
["COUNT", <subscription_id>, {"kinds": [1]}]
|
||||||
["COUNT", <subscription_id>, {"count": 93412452, "approximate": true}]
|
["COUNT", <subscription_id>, {"count": 93412452, "approximate": true}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Relay refuses to count
|
||||||
|
|
||||||
|
```
|
||||||
|
["COUNT", <subscription_id>, {"kinds": [4], "authors": [<pubkey>], "#p": [<pubkey>]}]
|
||||||
|
["CLOSED", <subscription_id>, "auth-required: cannot count other people's DMs"]
|
||||||
|
```
|
||||||
|
|
|
@ -172,6 +172,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||||
| `EVENT` | used to send events requested to clients | [01](01.md) |
|
| `EVENT` | used to send events requested to clients | [01](01.md) |
|
||||||
| `NOTICE` | used to send human-readable messages to clients | [01](01.md) |
|
| `NOTICE` | used to send human-readable messages to clients | [01](01.md) |
|
||||||
| `OK` | used to notify clients if an EVENT was successful | [01](01.md) |
|
| `OK` | used to notify clients if an EVENT was successful | [01](01.md) |
|
||||||
|
| `CLOSED` | used to notify clients that a REQ was ended and why | [01](01.md) |
|
||||||
| `AUTH` | used to send authentication challenges | [42](42.md) |
|
| `AUTH` | used to send authentication challenges | [42](42.md) |
|
||||||
| `COUNT` | used to send requested event counts to clients | [45](45.md) |
|
| `COUNT` | used to send requested event counts to clients | [45](45.md) |
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user