Skip to content

Commit

Permalink
Simplify text
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfranca committed Oct 12, 2023
1 parent 9ba1db1 commit 9bab3e6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 203 deletions.
87 changes: 0 additions & 87 deletions 20.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,4 @@ Command Results

`final` `mandatory` `author:jb55`

<<<<<<< HEAD
Moved to [NIP-01](01.md).
=======
When submitting events to relays, clients currently have no way to know if an event was successfully committed to the database. This NIP introduces the concept of command results which are like NOTICE's except provide more information about if an event was accepted or rejected.

A command result is a JSON object with the following structure that is returned when an event is successfully saved to the database or rejected:

["OK", <event_id>, <true|false>, <message>]

Relays MUST return `true` when the event is a duplicate and has already been saved. The `message` SHOULD start with `duplicate:` in this case.

Relays MUST return `false` when the event was rejected and not saved.

The `message` SHOULD provide additional information as to why the command succeeded or failed.

The `message` SHOULD start with `blocked:` if the pubkey or network address has been blocked, banned, or is not on a whitelist.

The `message` SHOULD start with `invalid:` if the event is invalid or doesn't meet some specific criteria (created_at is too far off, id is wrong, signature is wrong, etc)

The `message` SHOULD start with `pow:` if the event doesn't meet some proof-of-work difficulty. The client MAY consult the relay metadata at this point to retrieve the required posting difficulty.

The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques.

The `message` SHOULD start with `error:` if the event failed to save due to a server issue.

Ephemeral events are not acknowledged with OK responses, unless there is a failure.

If the event or `EVENT` command is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. This NIP only applies to non-malformed EVENT commands.


Examples
--------

Event successfully written to the database:

["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, ""]

Event successfully written to the database because of a reason:

["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, "pow: difficulty 25>=24"]

Event blocked due to ip filter

["OK", "b1a649ebe8...", false, "blocked: tor exit nodes not allowed"]

Event blocked due to pubkey ban

["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]

Event blocked, pubkey not registered

["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]

Event rejected, rate limited

["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]

Event rejected, `created_at` too far off

["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time. Is your system clock in sync?"]

Event rejected, insufficient proof-of-work difficulty

["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]

Event failed to save,

["OK", "b1a649ebe8...", false, "error: could not connect to the database"]



Client Handling
---------------

`messages` are meant for humans, with `reason:` prefixes so that clients can be slightly more intelligent with what to do with them. For example, with a `rate-limited:` reason the client may not show anything and simply try again with a longer timeout.

For the `pow:` prefix it may query relay metadata to get the updated difficulty requirement and try again in the background.

For the `invalid:` and `blocked:` prefix the client may wish to show these as styled error popups.

The prefixes include a colon so that the message can be cleanly separated from the prefix by taking everything after `:` and trimming it.


Future Extensions
-----------------

This proposal SHOULD be extended to support further commands in the future, such as REQ and AUTH. They are left out of this initial version to keep things simpler.
>>>>>>> 7908484 (Make NIP-42 fallback a requirement to NIP-43)
88 changes: 26 additions & 62 deletions 43.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,28 @@ 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.
This is a `client` to `relay` authentication procedure that
happens on connection start by using an `authorization` query parameter.
For example:

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)).
`new WebSocket("wss://relay.url?authorization=...")`

## Motivation

A relay may want to require clients to authenticate to access restricted resources. For example,
`Relays` may want to grant access to specific resources just to authenticated users.

For that, both `clients` and `relays` need to implement authentication. A simple authentication
procedure that `clients` can easily implement (just a query parameter) is better for driving adoption.

### Access Permission Examples

- Only paying user can publish events from his pubkey and republish events from other authors to the `relay`. If not a paying user or not authenticated, reply to event publishing attempts with `"OK"` message (as per [NIP-20](20.md)) indicating failure.
- Only paying user can read from `relay`. If not a paying user or not authenticated, reply to all subscriptions with `"EOSE"`.
- When user requests a DM event from `relay`, send it only to authenticated user if he is the author or the recipient.

- 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.
**Note:** "Paying user" examples could use other whitelisting means such as requiring users to have previously confirmed email or phone number or passed a CAPTCHA.

## How to Authenticate
## How Clients 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.
Expand All @@ -51,57 +52,20 @@ The resulting string is used as `authorization` query param when connecting to t
ws.addEventListener('close', () => console.log('disconnected') )
```

## Relay Handling
## How Relay Handle Authentication

`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:
`Relays` authenticate users with valid `authorization` query param.

The `authorization` query param must be percent-decoded into a nostr event that 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"]
```
- have the `relay` tag url value with the same domain name as the connected `relay`.

## 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"]] }]
```
The used protocol should be `wss` (WebSocket Secure).

`Relays` should validate the event as mentioned above, additionally checking if the `challenge` match the previously sent one.
Although not required, the authorization event `id` can 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 and
also disconnect the user that first used the event to authenticate.
54 changes: 0 additions & 54 deletions 65.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,61 +10,7 @@ Defines a replaceable event using `kind:10002` to advertise preferred relays for

The event MUST include a list of `r` tags with relay URIs and a `read` or `write` marker. If the marker is omitted, the relay is used for both purposes.

<<<<<<< HEAD
The `.content` is not used.
=======
The content is not used and SHOULD be an empty string.

The `r` tags can have a second parameter as either `read` or `write`. If it is omitted, it means the author uses the relay for both purposes.

Clients SHOULD, as with all replaceable events, use only the most recent kind-10002 event they can find.

### The meaning of read and write

Write relays are for events that are intended for anybody (e.g. your followers). Read relays are for events that address a particular person.

Clients SHOULD write feed-related events created by their user to their user's write relays.

Clients SHOULD read feed-related events created by another from at least some of that other person's write relays. Explicitly, they SHOULD NOT expect them to be available at their user's read relays. It SHOULD NOT be presumed that the user's read relays coincide with the write relays of the people the user follows.

Clients SHOULD read events that tag their user from their user's read relays.

Clients SHOULD write events that tag a person to at least some of that person's read relays. Explicitly, they SHOULD NOT expect that person will pick them up from their user's write relays. It SHOULD NOT be presumed that the user's write relays coincide with the read relays of the person being tagged.

Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see that author's feed-related events. But clients MAY presume otherwise.

### Motivation

There is a common nostr use case where users wish to follow the content produced by other users. This is evidenced by the implicit meaning of the Contact List in [NIP-02](02.md)

Because users don't often share the same sets of relays, ad-hoc solutions have arisen to get that content, but these solutions negatively impact scalability and decentralization:

- Most people are sending their posts to the same most popular relays in order to be more widely seen
- Many people are pulling from a large number of relays (including many duplicate events) in order to get more data
- Events are being copied between relays, oftentimes to many different relays

### Purposes

The purpose of this NIP is to help clients find the events of the people they follow, to help tagged events get to the people tagged, and to help nostr scale better.

### Suggestions

It is suggested that people spread their kind `10002` events to many relays, but write their normal feed-related events to a much smaller number of relays (between 2 to 6 relays). It is suggested that clients offer a way for users to spread their kind `10002` events to many more relays than they normally post to.

Authors may post events outside of the feed that they wish their followers to follow by posting them to relays outside of those listed in their "Relay List Metadata". For example, an author may want to reply to someone without all of their followers watching.

It is suggested that relays allow any user to write their own kind `10002` event (optionally with NIP-42/43 authentication to verify it is their own) even if they are not otherwise subscribed to the relay because

- finding where someone posts is rather important
- these events do not have content that needs management
- relays only need to store one replaceable event per pubkey to offer this service

### Why not in kind `0` Metadata

Even though this is user related metadata, it is a separate event from kind `0` in order to keep it small (as it should be widely spread) and to not have content that may require moderation by relay operators so that it is more acceptable to relays.

### Example
>>>>>>> 5e497ea (Edit NIP-42 instead of creating a new NIP)

```json
{
Expand Down

0 comments on commit 9bab3e6

Please sign in to comment.