Skip to content
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

add nip-42: authentication #141

Merged
merged 9 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions 42.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
NIP-42
======

Authentication of clients to relays
-----------------------------------

`draft` `optional` `author:Semisol` `author:fiatjaf`

This NIP defines a way for clients to authenticate to relays by signing an ephemeral event.

## 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 -- 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;
- 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.

## Protocol flow

This NIP defines a new message, `AUTH`, which clients can send to relays when they want to authenticate. The message is of the following form:

```
["AUTH", <signed-event>]
Giszmo marked this conversation as resolved.
Show resolved Hide resolved
```

The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and content must be set to the
WebSocket URL of the relay. `created_at` should be the current time. Example:
Semisol marked this conversation as resolved.
Show resolved Hide resolved

```json
{
"id": "...",
"pubkey": "...",
"created_at": 1669695536,
"kind": 22242,
"tags": [],
"content": "wss://relay.example.com/",
eskema marked this conversation as resolved.
Show resolved Hide resolved
"sig": "..."
}
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A proposal for what @Semisol suggested.

Suggested change
Clients can also send an empty `["AUTH"]` message. With this, relays should end any existing authentication of the websocket and must offer a new authentication challenge.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this. This shouldn't reset the authentication of the socket though, that could be done through ["AUTH", false] most likely

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, that makes it simpler and I get it now

Copy link
Collaborator

@Semisol Semisol Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A client may initiate the AUTH flow themselves by sending an AUTH command with no parameters, which the relay should respond to with a challenge string which should also deauthenticate the websocket:
```
["AUTH"]
```

The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right
The client may initiate the auth flow right before performing an action for which it knows authentication will be required -- for example, right

before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best.

Upon receiving a message from an unauthenticated user it can't fulfill without authentication, a relay may choose to notify the client. For
that it can use a `NOTICE` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we say it should be NOTICE for REQ and CLOSE and OK for EVENT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand Cameri's comment. Is this resolved? It's marked outdated but I see no REQ or CLOSE in the new diff.


```
["NOTICE", "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?"]
```

or it can return an `OK` message noting the reason an event was not written using the same prefix:

```
["OK", "b1a649ebe8...", false, "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"]
```

## Signed Event Verification

To verify `AUTH` messages, relays must ensure:

- that the `kind` is `22242`
- that the event was recently signed (~10 minutes, by `created_at`)
cameri marked this conversation as resolved.
Show resolved Hide resolved
Giszmo marked this conversation as resolved.
Show resolved Hide resolved
- that the `content` field matches the relay URL
- URL normalization techniques can be applied. For most cases just checking if the domain name is correct should be enough.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
- [NIP-35: User Discovery](35.md)
- [NIP-36: Sensitive Content](36.md)
- [NIP-40: Expiration Timestamp](40.md)
- [NIP-42: Authentication of clients to relays](42.md)

## Event Kinds

Expand All @@ -47,18 +48,20 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
| 43 | Channel Hide Message | [28](28.md) |
| 44 | Channel Mute User | [28](28.md) |
| 45-49 | Public Chat Reserved | [28](28.md) |
| 22242 | Client Authentication | [42](42.md) |
| 10000-19999 | Replaceable Events Reserved | [16](16.md) |
| 20000-29999 | Ephemeral Events Reserved | [16](16.md) |


## Message types

### Client to Relay
| type | description | NIP |
|-------|-----------------------------------------------------|------------|
| EVENT | used to publish events | [1](01.md) |
| REQ | used to request events and subscribe to new updates | [1](01.md) |
| CLOSE | used to stop previous subscriptions | [1](01.md) |
| type | description | NIP |
|-------|-----------------------------------------------------|-------------|
| EVENT | used to publish events | [1](01.md) |
| REQ | used to request events and subscribe to new updates | [1](01.md) |
| CLOSE | used to stop previous subscriptions | [1](01.md) |
| AUTH | used to send authentication events | [42](42.md) |

### Relay to Client
| type | description | NIP |
Expand Down