2022-08-04 04:33:38 -04:00
NIP: 26
=======
Delegated Event Signing
-----
2022-08-24 08:24:50 -04:00
`draft` `optional` `author:markharding` `author:minds`
2022-08-04 04:33:38 -04:00
2022-08-24 08:24:50 -04:00
This NIP defines how events can be delegated so that they can be signed by other keypairs.
2022-08-04 04:33:38 -04:00
Another application of this proposal is to abstract away the use of the 'root' keypairs when interacting with clients. For example, a user could generate new keypairs for each client they wish to use and authorize those keypairs to generate events on behalf of their root pubkey, where the root keypair is stored in cold storage.
2022-08-24 08:24:50 -04:00
#### Introducing the 'delegation' tag
2022-08-04 04:33:38 -04:00
2022-08-24 08:24:50 -04:00
This NIP introduces a new tag: `delegation` which is formatted as follows:
2022-08-04 04:33:38 -04:00
```json
[
2022-08-24 08:24:50 -04:00
"delegation",
< pubkey of the delegator > ,
< conditions query string > ,
2023-02-13 06:34:12 -05:00
< delegation token: 64-byte Schnorr signature of the sha256 hash of the delegation string >
2022-08-04 04:33:38 -04:00
]
```
2022-08-24 08:24:50 -04:00
##### Delegation Token
2022-08-04 04:33:38 -04:00
2023-01-07 18:12:48 -05:00
The **delegation token** should be a 64-byte Schnorr signature of the sha256 hash of the following string:
2022-08-04 04:33:38 -04:00
2022-08-24 08:24:50 -04:00
```
nostr:delegation:< pubkey of publisher ( delegatee ) > :< conditions query string >
2022-08-04 04:33:38 -04:00
```
2023-01-27 06:11:27 -05:00
##### Conditions Query String
The following fields and operators are supported in the above query string:
*Fields*:
1. `kind`
- *Operators* :
2023-02-08 06:36:07 -05:00
- `=${KIND_NUMBER}` - delegatee may only sign events of this kind
2023-01-27 06:11:27 -05:00
2. `created_at`
- *Operators* :
2023-02-08 06:36:07 -05:00
- `<${TIMESTAMP}` - delegatee may only sign events created ** *before*** the specified timestamp
- `>${TIMESTAMP}` - delegatee may only sign events created ** *after*** the specified timestamp
2023-01-27 06:11:27 -05:00
2023-02-08 06:36:07 -05:00
In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&` .
2023-01-27 06:11:27 -05:00
2023-02-06 10:21:58 -05:00
For example, the following condition strings are valid:
2023-02-08 06:36:07 -05:00
2023-01-27 06:11:27 -05:00
- `kind=1&created_at<1675721813`
2023-02-08 06:36:07 -05:00
- `kind=0&kind=1&created_at>1675721813`
2023-01-27 06:11:27 -05:00
- `kind=1&created_at>1674777689&created_at<1675721813`
2022-08-04 04:33:38 -04:00
2023-02-01 07:05:25 -05:00
For the vast majority of use-cases, it is advisable that query strings should include a `created_at` ** *after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf.
2023-01-07 18:12:48 -05:00
#### Example
2022-08-04 04:33:38 -04:00
```
2023-01-07 18:12:48 -05:00
# Delegator:
privkey: ee35e8bb71131c02c1d7e73231daa48e9953d329a4b701f7133c8f46dd21139c
pubkey: 8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd
2022-08-04 04:33:38 -04:00
2023-01-07 18:12:48 -05:00
# Delegatee:
privkey: 777e4f60b4aa87937e13acc84f7abcc3c93cc035cb4c1e9f7a9086dd78fffce1
pubkey: 477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396
```
2023-02-01 07:05:25 -05:00
Delegation string to grant note publishing authorization to the delegatee (477318cf) from now, for the next 30 days, given the current timestamp is `1674834236` .
2023-01-07 18:12:48 -05:00
```json
2023-02-01 07:05:25 -05:00
nostr:delegation:477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396:kind=1& created_at>1674834236& created_at< 1677426236
2023-01-07 18:12:48 -05:00
```
2022-08-04 04:33:38 -04:00
2023-02-01 07:05:25 -05:00
The delegator (8e0d3d3e) then signs a SHA256 hash of the above delegation string, the result of which is the delegation token:
2023-01-07 18:12:48 -05:00
```
2023-02-01 07:05:25 -05:00
6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524
2023-01-07 18:12:48 -05:00
```
2022-08-04 04:33:38 -04:00
2023-01-07 18:12:48 -05:00
The delegatee (477318cf) can now construct an event on behalf of the delegator (8e0d3d3e). The delegatee then signs the event with its own private key and publishes.
2022-08-04 04:33:38 -04:00
```json
{
2023-02-01 07:05:25 -05:00
"id": "e93c6095c3db1c31d15ac771f8fc5fb672f6e52cd25505099f62cd055523224f",
2023-01-07 18:12:48 -05:00
"pubkey": "477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396",
2023-02-01 07:05:25 -05:00
"created_at": 1677426298,
2022-08-24 08:24:50 -04:00
"kind": 1,
"tags": [
[
"delegation",
2023-01-07 18:12:48 -05:00
"8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd",
2023-02-01 07:05:25 -05:00
"kind=1& created_at>1674834236& created_at< 1677426236 " ,
"6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524"
2022-08-24 08:24:50 -04:00
]
],
2023-01-07 18:12:48 -05:00
"content": "Hello, world!",
2023-02-01 07:05:25 -05:00
"sig": "633db60e2e7082c13a47a6b19d663d45b2a2ebdeaf0b4c35ef83be2738030c54fc7fd56d139652937cdca875ee61b51904a1d0d0588a6acd6168d7be2909d693"
2022-08-04 04:33:38 -04:00
}
```
2023-02-01 07:05:25 -05:00
The event should be considered a valid delegation if the conditions are satisfied (`kind=1`, `created_at>1674834236` and `created_at<1677426236` in this example) and, upon validation of the delegation token, are found to be unchanged from the conditions in the original delegation string.
2023-01-07 18:12:48 -05:00
Clients should display the delegated note as if it was published directly by the delegator (8e0d3d3e).
2022-08-24 08:24:50 -04:00
2023-04-13 08:31:35 -04:00
#### Relay & Client Support
2022-08-24 08:24:50 -04:00
2023-04-13 08:31:35 -04:00
Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value.
2023-06-01 09:42:31 -04:00
Relays SHOULD allow the delegator (8e0d3d3e) to delete the events published by the delegatee (477318cf).
#### Protocol Handler Support
Using NIP26, a new oauth-style protocol handler can allow oauth-style login for nostr apps that do not want to be the primary custodians of identity keys.:
Consider the following link that can be opened as an intent in browser and mobile apps:
```url
2023-06-01 09:47:49 -04:00
nkey://auth?id=< uuid > & uri=< uri > & kinds=1,2,4,5& action=delegate& from=< epoch > & to=< epoch > & pubkey=< 64-char hex pub key > & relays=r1,r2...
2023-06-01 09:42:31 -04:00
```
2023-06-01 09:47:49 -04:00
This can open up an associated app or browser that displays the requesting URI information in detail, including certificate information.
Care must be taken to let the user know the full scope requested, the ability of the app to be able to post the kinds requested, etc.
2023-06-01 09:42:31 -04:00
- On success:
- Posts NIP26 delegate info to the requested relays (if any)
- Optionally posts delegate info to additional relays (if configured
2023-06-01 09:47:49 -04:00
- POSTs a response to the **uri** containing a delegate key encrypted with the requested pubkey and information about what was approved (if anything)
2023-06-01 09:42:31 -04:00
```js
{
id:"< request-id > ",
status:"authorized",
key:"< b64 encoded nip44 encrypted with the **pubkey** > ",
from:< epoch-approved-from-time >
to:< epoch-approved-to-time > ,
kinds: [1,2]
}
```
2023-06-01 09:47:49 -04:00
-On rejection, POSTs a "rejection" to the **uri**
2023-06-01 09:49:29 -04:00
```js
{
2023-06-01 09:42:31 -04:00
id:"< request-id > ",
status:"denied",
}
2023-06-01 09:49:29 -04:00
```
This should help alleviate the need for apps to ask users to paste in NSECs. Instead a single app can be used, such as alby, etc.