Skip to content

Commit ea422ca

Browse files
committed
NIP 49: Nostr Wallet Auth
1 parent c07f0ea commit ea422ca

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

49.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
NIP-49
2+
======
3+
4+
Nostr Wallet Auth
5+
--------------------
6+
7+
`draft` `optional`
8+
9+
## Rationale
10+
11+
[Nostr Wallet Connect](47.md) is a protocol for talking to a lightning wallet over nostr. It is great but hinges on
12+
having the user copy-paste a wallet connection URI into the app they wish to connect with. This can be a UX hurdle and
13+
often has the user handling sensitive information that they may not understand.
14+
15+
As well, Nostr Wallet Connect has lots of different functions that a wallet may or may not support or an app may or may
16+
not need. This either runs into silent failures or requires the user to understand what functions their wallet supports
17+
and what functions the app needs.
18+
19+
Finally, Nostr Wallet Connect requires the wallet to generate both key pairs and the app to use these. This limits the
20+
key management strategies that an app can use and often leads to suboptimal key management.
21+
22+
This NIP proposes a new protocol that solves these problems by having the wallet and app generate the parameters for a
23+
NWC connection together. This URI is then used to connect the wallet and app.
24+
25+
## Terms
26+
27+
- **app**: Nostr app on any platform that wants to permissioned access to a user's lightning wallet.
28+
- **wallet**: A nostr wallet connect capable lightning wallet that the user wants to connect to the app.
29+
30+
## Theory of Operation
31+
32+
1. The user wants to connect their wallet to an app. The app provides a QR code or other means of connecting to the app.
33+
The QR code contains a `nostr+walletauth://` URI that contains the app's public key, the relay to communicate over,
34+
and a list of functions that the app requires.
35+
2. The user scans the QR code and their wallet prompts them the required functions and asks them to confirm that they
36+
want to connect to the app.
37+
3. On confirmation, the wallet generates a new key pair and sends the public key to the app in a confirmation event.
38+
4. With the combination of both keys, the wallet and the app both will generate the same connection URI. They can now
39+
use NWC to communicate.
40+
41+
## Specification
42+
43+
### URI Format
44+
45+
The **app** generates this connection URI with protocol `nostr+walletauth:` and base path it's hex-encoded `pubkey`
46+
with the following query string parameters:
47+
48+
- `relay` Required. URL of the relay where the **app** is connected and will be listening for events. May be
49+
more than one.
50+
- `secret` Required. A random identifier that the **wallet** will use to identify the connection. Without this the
51+
**app** cannot authenticate they are receiving a message from the user they want, it could be an attacker just sending
52+
kind `33194` events to the **app**. This should be unique for each connection. This is not a key and should be
53+
different for every new URI.
54+
- `required_commands` Required. A space-separated list of commands that the **app** requires from the **wallet**. The
55+
**wallet** MUST NOT connect if it does not support all of these permissions.
56+
- `optional_commands` Optional. A space-separated list of commands that the **wallet** can enable to add additional
57+
functionality. The **wallet** MAY ignore these.
58+
- `budget` Optional. A budget that the **wallet** will use to limit the amount of funds that the **app** can spend.
59+
The **app** MUST NOT spend more than this amount. The budget is a string of the form `max_amount/period`.
60+
The `period` is one of `daily`, `weekly`, `monthly`, `yearly`. The `max_amount` is a satoshi amount.
61+
- `identity` Optional. The hex-encoded `pubkey` of the *app* that the **wallet** is connecting to. This is used to
62+
for the wallet to display to the user. The **wallet** MAY ignore this.
63+
64+
#### Example URI
65+
66+
```sh
67+
nostr+walletauth://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=b8a30fafa48d4795b6c0eec169a383de&required_commands=pay_invoice%20pay_keysend%20make_invoice%20lookup_invoice&optional_commands=list_transactions&budget=10000%2Fdaily
68+
```
69+
70+
### Event
71+
72+
This NIP only uses one event kind `33194`. We use a parameterized replaceable event to allow for the wallet and app to
73+
renegotiate the connection if needed and to allow for the wallet being able to look up the connection details later.
74+
75+
The event SHOULD contain one `d` tag, containing the public key of the app from the URI.
76+
77+
The content of the event is encrypted with [NIP04](04.md), and should be a JSON structure as follows:
78+
79+
```jsonc
80+
{
81+
"secret": "b8a30fafa48d4795b6c0eec169a383de", // string, the secret from the URI
82+
"commands": [ // array of strings, commands that the wallet agrees to support
83+
"pay_invoice",
84+
"pay_keysend",
85+
"make_invoice",
86+
"lookup_invoice",
87+
"list_transactions",
88+
],
89+
"relay": "wss://relay.damus.io", // Optional string, alternative relay that the wallet will use
90+
"lud16": "user@example.com", // Optional string, user's lightning address
91+
}
92+
```
93+
94+
After the user approves the connection, the wallet should send this event to the **app**.
95+
96+
The *app* should validate that the `secret` matches the one in the URI and that the `commands` are a subset of the
97+
`required_commands` and `optional_commands` from the URI. If the `relay` is present, the *app* should use that instead
98+
of the one from the URI.
99+
100+
The wallet and app should both then have all the necessary information be able to communicate using NWC. The app will
101+
have the wallet's key from the event's pubkey. The wallet will have the app's key from the URI.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
5656
- [NIP-46: Nostr Connect](46.md)
5757
- [NIP-47: Wallet Connect](47.md)
5858
- [NIP-48: Proxy Tags](48.md)
59+
- [NIP-49: Wallet Auth](49.md)
5960
- [NIP-50: Search Capability](50.md)
6061
- [NIP-51: Lists](51.md)
6162
- [NIP-52: Calendar Events](52.md)
@@ -147,6 +148,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
147148
| `31925` | Calendar Event RSVP | [52](52.md) |
148149
| `31989` | Handler recommendation | [89](89.md) |
149150
| `31990` | Handler information | [89](89.md) |
151+
| `33194` | Nostr Wallet Auth | [49](49.md) |
150152
| `34550` | Community Definition | [72](72.md) |
151153

152154
[nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md

0 commit comments

Comments
 (0)