diff options
| -rw-r--r-- | internal/auth/README.md | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/internal/auth/README.md b/internal/auth/README.md index adfe260..c41b6cb 100644 --- a/internal/auth/README.md +++ b/internal/auth/README.md | |||
| @@ -6,6 +6,58 @@ This package implements [NIP-98](https://github.com/nostr-protocol/nips/blob/mas | |||
| 6 | 6 | ||
| 7 | NIP-98 provides HTTP authentication using Nostr event signatures instead of bearer tokens or OAuth2. It uses cryptographic signatures to prove the request came from a specific public key, without requiring passwords or centralized identity providers. | 7 | NIP-98 provides HTTP authentication using Nostr event signatures instead of bearer tokens or OAuth2. It uses cryptographic signatures to prove the request came from a specific public key, without requiring passwords or centralized identity providers. |
| 8 | 8 | ||
| 9 | ## Relationship to NIP-42 | ||
| 10 | |||
| 11 | This implementation serves as **NIP-42 for gRPC**, with some important distinctions: | ||
| 12 | |||
| 13 | ### For Reads (Queries/Subscriptions) | ||
| 14 | |||
| 15 | **NIP-42 (WebSocket)**: | ||
| 16 | - Authenticates the **connection** once via challenge-response | ||
| 17 | - All subsequent REQ messages use the authenticated connection | ||
| 18 | - Enables access control for private/restricted events | ||
| 19 | |||
| 20 | **NIP-98 (gRPC - this implementation)**: | ||
| 21 | - Authenticates **streaming RPCs** once at stream establishment | ||
| 22 | - All events streamed over that authenticated connection | ||
| 23 | - Same access control pattern as NIP-42 | ||
| 24 | |||
| 25 | **Result**: Functionally identical! Both authenticate once and stream many events. | ||
| 26 | |||
| 27 | ``` | ||
| 28 | WebSocket + NIP-42: AUTH challenge → Subscribe → 1000 events (no re-auth) | ||
| 29 | gRPC + NIP-98: Subscribe with auth → 1000 events (no re-auth) | ||
| 30 | ``` | ||
| 31 | |||
| 32 | ### For Writes (Publishing Events) | ||
| 33 | |||
| 34 | **NIP-42 (WebSocket)**: | ||
| 35 | - Not applicable - events are self-authenticating via `event.sig` | ||
| 36 | - No connection-level auth for EVENT messages | ||
| 37 | - Relay only verifies the event signature | ||
| 38 | |||
| 39 | **NIP-98 (gRPC - this implementation)**: | ||
| 40 | - Adds **relay access control** on top of event signatures | ||
| 41 | - Proves who is **submitting** (NIP-98) vs who **created** (event.sig) the event | ||
| 42 | - Enables use cases like: | ||
| 43 | - Rate limiting per user | ||
| 44 | - Allow-lists for relay access | ||
| 45 | - Preventing spam/abuse (submitting scraped events) | ||
| 46 | - Verifying submitter matches event author | ||
| 47 | |||
| 48 | **Result**: Standardizes a relay access control pattern beyond base Nostr's self-authenticating events. | ||
| 49 | |||
| 50 | ### Summary | ||
| 51 | |||
| 52 | | Use Case | WebSocket (NIP-42) | gRPC (NIP-98) | | ||
| 53 | |----------|-------------------|---------------| | ||
| 54 | | **Read auth** | Challenge-response, once per connection | Per-RPC auth, once per stream | | ||
| 55 | | **Read pattern** | ✅ Same: authenticate once, stream many | ✅ Same: authenticate once, stream many | | ||
| 56 | | **Write auth** | ❌ N/A (events self-auth) | ✅ Optional relay access control | | ||
| 57 | | **Overhead** | None after initial handshake | None for streams; minimal for unary calls | | ||
| 58 | |||
| 59 | This implementation gives you NIP-42's read authentication pattern plus standardized relay access control for writes. | ||
| 60 | |||
| 9 | ## How It Works | 61 | ## How It Works |
| 10 | 62 | ||
| 11 | ### Authentication Flow | 63 | ### Authentication Flow |
| @@ -167,10 +219,14 @@ authOpts := &auth.InterceptorOptions{ | |||
| 167 | 219 | ||
| 168 | 1. **No passwords**: Uses public key cryptography | 220 | 1. **No passwords**: Uses public key cryptography |
| 169 | 2. **Decentralized**: No central identity provider | 221 | 2. **Decentralized**: No central identity provider |
| 170 | 3. **Per-request auth**: Each request is independently authenticated | 222 | 3. **Nostr ecosystem compatible**: |
| 171 | 4. **Nostr compatible**: Works with existing Nostr identities and tools | 223 | - Same authentication as NIP-42 for WebSocket relays |
| 172 | 5. **Standard pattern**: Uses industry-standard gRPC credentials interface | 224 | - Works with existing Nostr identities (npub/nsec) |
| 173 | 6. **Key rotation**: Easy to rotate keys without server-side updates | 225 | - Compatible with Nostr clients and tools |
| 226 | 4. **Efficient for streaming**: Authenticate once per stream (like NIP-42 for WebSocket) | ||
| 227 | 5. **Standard gRPC pattern**: Drop-in replacement for OAuth2/JWT using `credentials.PerRPCCredentials` | ||
| 228 | 6. **Flexible access control**: Enables relay-level permissions beyond event signatures | ||
| 229 | 7. **Key rotation**: Easy to rotate keys without server-side session management | ||
| 174 | 230 | ||
| 175 | ## Compatibility | 231 | ## Compatibility |
| 176 | 232 | ||
