diff options
| author | bndw <ben@bdw.to> | 2026-02-14 14:33:01 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-14 14:33:01 -0800 |
| commit | 212154fc29e3631d13cf7af9a0a3046c9683173b (patch) | |
| tree | 8eddb5e01d25dfadcd078bd10274d13f2d936d06 /cmd/relay | |
| parent | dbfc55ed1aec5faefacfcfbd51c4de06b316fa90 (diff) | |
feat: implement NIP-42 WebSocket authentication
Add support for authenticating WebSocket clients using NIP-42 protocol,
enabling auth restrictions for normal Nostr clients.
Storage layer (internal/storage/auth.go):
- CreateAuthChallenge() - Generate random 32-byte challenge with 10min TTL
- ValidateAndConsumeChallenge() - Verify challenge validity and mark as used
- CleanupExpiredChallenges() - Remove old challenges from database
- Uses existing auth_challenges table
WebSocket handler (internal/handler/websocket/handler.go):
- Track authenticatedPubkey per connection
- Track authChallenge per connection
- requireAuth() - Check if operation requires authentication
- handleAuth() - Process AUTH responses (kind 22242 events)
- sendAuthChallenge() - Send AUTH challenge to client
- Enforce auth on EVENT (writes) and REQ (reads) messages
- Support separate read/write allowlists
Main (cmd/relay/main.go):
- Wire auth config from YAML to WebSocket handler
- Pass read/write enabled flags and allowed npub lists
NIP-42 Flow:
1. Client sends EVENT/REQ without auth
2. If auth required, relay sends: ["AUTH", "<challenge>"]
3. Client signs kind 22242 event with challenge tag
4. Client sends: ["AUTH", <signed-event>]
5. Relay validates signature, challenge, and allowlist
6. Connection marked as authenticated
7. Client can now EVENT/REQ
Example config to restrict writes to your npub:
```yaml
auth:
write:
enabled: true
allowed_npubs:
- npub1your-npub-here...
```
WebSocket clients (Damus, Amethyst, etc.) can now authenticate!
Diffstat (limited to 'cmd/relay')
| -rw-r--r-- | cmd/relay/main.go | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/cmd/relay/main.go b/cmd/relay/main.go index 8948ebf..6974f65 100644 --- a/cmd/relay/main.go +++ b/cmd/relay/main.go | |||
| @@ -115,6 +115,15 @@ func main() { | |||
| 115 | }() | 115 | }() |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | if cfg.Auth.Read.Enabled || cfg.Auth.Write.Enabled { | ||
| 119 | wsHandler.SetAuthConfig(&wshandler.AuthConfig{ | ||
| 120 | ReadEnabled: cfg.Auth.Read.Enabled, | ||
| 121 | WriteEnabled: cfg.Auth.Write.Enabled, | ||
| 122 | ReadAllowedPubkeys: cfg.Auth.Read.AllowedNpubs, | ||
| 123 | WriteAllowedPubkeys: cfg.Auth.Write.AllowedNpubs, | ||
| 124 | }) | ||
| 125 | } | ||
| 126 | |||
| 118 | var grpcDisplay, httpDisplay, wsDisplay string | 127 | var grpcDisplay, httpDisplay, wsDisplay string |
| 119 | if cfg.Server.PublicURL != "" { | 128 | if cfg.Server.PublicURL != "" { |
| 120 | grpcDisplay = cfg.Server.PublicURL + ":443" | 129 | grpcDisplay = cfg.Server.PublicURL + ":443" |
