From 212154fc29e3631d13cf7af9a0a3046c9683173b Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 14 Feb 2026 14:33:01 -0800 Subject: 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", ""] 3. Client signs kind 22242 event with challenge tag 4. Client sends: ["AUTH", ] 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! --- cmd/relay/main.go | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'cmd') 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() { }() } + if cfg.Auth.Read.Enabled || cfg.Auth.Write.Enabled { + wsHandler.SetAuthConfig(&wshandler.AuthConfig{ + ReadEnabled: cfg.Auth.Read.Enabled, + WriteEnabled: cfg.Auth.Write.Enabled, + ReadAllowedPubkeys: cfg.Auth.Read.AllowedNpubs, + WriteAllowedPubkeys: cfg.Auth.Write.AllowedNpubs, + }) + } + var grpcDisplay, httpDisplay, wsDisplay string if cfg.Server.PublicURL != "" { grpcDisplay = cfg.Server.PublicURL + ":443" -- cgit v1.2.3