mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-23 17:05:51 -05:00
NIP 67: Nostr Wallet Auth
This commit is contained in:
parent
9efafe2294
commit
ac241c1701
101
67.md
Normal file
101
67.md
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
NIP-67
|
||||||
|
======
|
||||||
|
|
||||||
|
Nostr Wallet Auth
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
`draft` `optional`
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
|
||||||
|
[Nostr Wallet Connect](47.md) is a protocol for talking to a lightning wallet over nostr. It is great but hinges on
|
||||||
|
having the user copy-paste a wallet connection URI into the app they wish to connect with. This can be a UX hurdle and
|
||||||
|
often has the user handling sensitive information that they may not understand.
|
||||||
|
|
||||||
|
As well, Nostr Wallet Connect has lots of different functions that a wallet may or may not support or an app may or may
|
||||||
|
not need. This either runs into silent failures or requires the user to understand what functions their wallet supports
|
||||||
|
and what functions the app needs.
|
||||||
|
|
||||||
|
Finally, Nostr Wallet Connect requires the wallet to generate both key pairs and the app to use these. This limits the
|
||||||
|
key management strategies that an app can use and often leads to suboptimal key management.
|
||||||
|
|
||||||
|
This NIP proposes a new protocol that solves these problems by having the wallet and app generate the parameters for a
|
||||||
|
NWC connection together. This URI is then used to connect the wallet and app.
|
||||||
|
|
||||||
|
## Terms
|
||||||
|
|
||||||
|
- **app**: Nostr app on any platform that wants to permissioned access to a user's lightning wallet.
|
||||||
|
- **wallet**: A nostr wallet connect capable lightning wallet that the user wants to connect to the app.
|
||||||
|
|
||||||
|
## Theory of Operation
|
||||||
|
|
||||||
|
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.
|
||||||
|
The QR code contains a `nostr+walletauth://` URI that contains the app's public key, the relay to communicate over,
|
||||||
|
and a list of functions that the app requires.
|
||||||
|
2. The user scans the QR code and their wallet prompts them the required functions and asks them to confirm that they
|
||||||
|
want to connect to the app.
|
||||||
|
3. On confirmation, the wallet generates a new key pair and sends the public key to the app in a confirmation event.
|
||||||
|
4. With the combination of both keys, the wallet and the app both will generate the same connection URI. They can now
|
||||||
|
use NWC to communicate.
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
### URI Format
|
||||||
|
|
||||||
|
The **app** generates this connection URI with protocol `nostr+walletauth:` and base path it's hex-encoded `pubkey`
|
||||||
|
with the following query string parameters:
|
||||||
|
|
||||||
|
- `relay` Required. URL of the relay where the **app** is connected and will be listening for events. May be
|
||||||
|
more than one.
|
||||||
|
- `secret` Required. A random identifier that the **wallet** will use to identify the connection. Without this the
|
||||||
|
**app** cannot authenticate they are receiving a message from the user they want, it could be an attacker just sending
|
||||||
|
kind `33194` events to the **app**. This should be unique for each connection. This is not a key and should be
|
||||||
|
different for every new URI.
|
||||||
|
- `required_commands` Required. A space-separated list of commands that the **app** requires from the **wallet**. The
|
||||||
|
**wallet** MUST NOT connect if it does not support all of these permissions.
|
||||||
|
- `optional_commands` Optional. A space-separated list of commands that the **wallet** can enable to add additional
|
||||||
|
functionality. The **wallet** MAY ignore these.
|
||||||
|
- `budget` Optional. A budget that the **wallet** will use to limit the amount of funds that the **app** can spend.
|
||||||
|
The **app** MUST NOT spend more than this amount. The budget is a string of the form `max_amount/period`.
|
||||||
|
The `period` is one of `daily`, `weekly`, `monthly`, `yearly`. The `max_amount` is a satoshi amount.
|
||||||
|
- `identity` Optional. The hex-encoded `pubkey` of the *app* that the **wallet** is connecting to. This is used to
|
||||||
|
for the wallet to display to the user. The **wallet** MAY ignore this.
|
||||||
|
|
||||||
|
#### Example URI
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event
|
||||||
|
|
||||||
|
This NIP only uses one event kind `33194`. We use a parameterized replaceable event to allow for the wallet and app to
|
||||||
|
renegotiate the connection if needed and to allow for the wallet being able to look up the connection details later.
|
||||||
|
|
||||||
|
The event SHOULD contain one `d` tag, containing the public key of the app from the URI.
|
||||||
|
|
||||||
|
The content of the event is encrypted with [NIP04](04.md), and should be a JSON structure as follows:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"secret": "b8a30fafa48d4795b6c0eec169a383de", // string, the secret from the URI
|
||||||
|
"commands": [ // array of strings, commands that the wallet agrees to support
|
||||||
|
"pay_invoice",
|
||||||
|
"pay_keysend",
|
||||||
|
"make_invoice",
|
||||||
|
"lookup_invoice",
|
||||||
|
"list_transactions",
|
||||||
|
],
|
||||||
|
"relay": "wss://relay.damus.io", // Optional string, alternative relay that the wallet will use
|
||||||
|
"lud16": "user@example.com", // Optional string, user's lightning address
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After the user approves the connection, the wallet should send this event to the **app**.
|
||||||
|
|
||||||
|
The *app* should validate that the `secret` matches the one in the URI and that the `commands` are a subset of the
|
||||||
|
`required_commands` and `optional_commands` from the URI. If the `relay` is present, the *app* should use that instead
|
||||||
|
of the one from the URI.
|
||||||
|
|
||||||
|
The wallet and app should both then have all the necessary information be able to communicate using NWC. The app will
|
||||||
|
have the wallet's key from the event's pubkey. The wallet will have the app's key from the URI.
|
|
@ -66,6 +66,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||||
- [NIP-57: Lightning Zaps](57.md)
|
- [NIP-57: Lightning Zaps](57.md)
|
||||||
- [NIP-58: Badges](58.md)
|
- [NIP-58: Badges](58.md)
|
||||||
- [NIP-65: Relay List Metadata](65.md)
|
- [NIP-65: Relay List Metadata](65.md)
|
||||||
|
- [NIP-67: Wallet Auth](67.md)
|
||||||
- [NIP-72: Moderated Communities](72.md)
|
- [NIP-72: Moderated Communities](72.md)
|
||||||
- [NIP-75: Zap Goals](75.md)
|
- [NIP-75: Zap Goals](75.md)
|
||||||
- [NIP-78: Application-specific data](78.md)
|
- [NIP-78: Application-specific data](78.md)
|
||||||
|
@ -155,6 +156,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||||
| `31925` | Calendar Event RSVP | [52](52.md) |
|
| `31925` | Calendar Event RSVP | [52](52.md) |
|
||||||
| `31989` | Handler recommendation | [89](89.md) |
|
| `31989` | Handler recommendation | [89](89.md) |
|
||||||
| `31990` | Handler information | [89](89.md) |
|
| `31990` | Handler information | [89](89.md) |
|
||||||
|
| `33194` | Nostr Wallet Auth | [49](49.md) |
|
||||||
| `34550` | Community Definition | [72](72.md) |
|
| `34550` | Community Definition | [72](72.md) |
|
||||||
|
|
||||||
[nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md
|
[nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md
|
||||||
|
|
Loading…
Reference in New Issue
Block a user