From c573c465f09d319518c23c8b2ffa72a384f34b23 Mon Sep 17 00:00:00 2001 From: Dylan Cant Date: Sun, 15 Jan 2023 23:33:53 -0500 Subject: [PATCH 1/3] fixed typos added docstring --- handlers.go | 6 +++--- interface.go | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/handlers.go b/handlers.go index 122e3f5..661b660 100644 --- a/handlers.go +++ b/handlers.go @@ -16,7 +16,7 @@ import ( "golang.org/x/exp/slices" ) -// TODO: consdier moving these to Server as config params +// TODO: consider moving these to Server as config params const ( // Time allowed to write a message to the peer. writeWait = 10 * time.Second @@ -31,7 +31,7 @@ const ( maxMessageSize = 512000 ) -// TODO: consdier moving these to Server as config params +// TODO: consider moving these to Server as config params var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, @@ -211,7 +211,7 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { } if (len(senders) == 1 && senders[0] != ws.authed) || (len(receivers) == 1 && receivers[0] != ws.authed) { - notice = "restricted: can't serve kind-4 to their participants" + notice = "restricted: can only serve kind-4 to their participants" return } } diff --git a/interface.go b/interface.go index bceefed..5d24cf2 100644 --- a/interface.go +++ b/interface.go @@ -29,6 +29,8 @@ type Relay interface { Storage() Storage } +// Auther is the interface for implementing NIP-42. +// ServiceURL() returns the URL used to verify the "AUTH" event from clients. type Auther interface { ServiceURL() string } From cf3f94f4de042c57a32015a5a227cd5e5e80d521 Mon Sep 17 00:00:00 2001 From: Dylan Cant Date: Mon, 16 Jan 2023 01:24:35 -0500 Subject: [PATCH 2/3] Added an "OK" signal when authenticated (or not) To interact with okCallback in go-nostr relay.go. --- handlers.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/handlers.go b/handlers.go index 661b660..fc89d7d 100644 --- a/handlers.go +++ b/handlers.go @@ -53,7 +53,7 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { s.clients[conn] = struct{}{} ticker := time.NewTicker(pingPeriod) - // nip-42 challenge + // NIP-42 challenge challenge := make([]byte, 8) rand.Read(challenge) @@ -82,7 +82,7 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { return nil }) - // nip42 auth challenge + // NIP-42 auth challenge if _, ok := s.relay.(Auther); ok { ws.WriteJSON([]interface{}{"AUTH", ws.challenge}) } @@ -260,6 +260,9 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { } if pubkey, ok := nip42.ValidateAuthEvent(&evt, ws.challenge, auther.ServiceURL()); ok { ws.authed = pubkey + ws.WriteJSON([]interface{}{"OK", evt.ID, true, "authentication success"}) + } else { + ws.WriteJSON([]interface{}{"OK", evt.ID, false, "error: failed to authenticate"}) } } default: From cab065451654b7d3a2007a8aab7f823b6c79df49 Mon Sep 17 00:00:00 2001 From: Dylan Cant Date: Mon, 16 Jan 2023 21:29:35 -0500 Subject: [PATCH 3/3] small fixes to NIP-42 parts of handlers.go also removed "break" commands at ends of cases in switch statement (these are unnecessary in `go`, cf https://go.dev/tour/flowcontrol/9) --- handlers.go | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/handlers.go b/handlers.go index fc89d7d..f745024 100644 --- a/handlers.go +++ b/handlers.go @@ -177,7 +177,6 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { ok, message := AddEvent(s.relay, evt) ws.WriteJSON([]interface{}{"OK", evt.ID, ok, message}) - break case "REQ": var id string json.Unmarshal(request[1], &id) @@ -202,16 +201,22 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { // only when authentication is a thing if _, ok := s.relay.(Auther); ok { if slices.Contains(filter.Kinds, 4) { - // when fetching kind-4 one must be either on the sending or on the receiving end senders := filter.Authors - receivers, _ := filter.Tags["e"] - if len(senders) > 1 || len(receivers) > 1 { - notice = "restricted: can't serve kind-4 messages to or from more than one key" + receivers, _ := filter.Tags["p"] + switch { + case ws.authed == "": + // not authenticated + notice = "restricted: this relay does not serve kind-4 to unauthenticated users, does your client implement NIP-42?" return - } - if (len(senders) == 1 && senders[0] != ws.authed) || - (len(receivers) == 1 && receivers[0] != ws.authed) { - notice = "restricted: can only serve kind-4 to their participants" + case len(senders) == 1 && len(receivers) < 2 && (senders[0] == ws.authed): + // allowed filter: ws.authed is sole sender (filter specifies one or all receivers) + case len(receivers) == 1 && len(senders) < 2 && (receivers[0] == ws.authed): + // allowed filter: ws.authed is sole receiver (filter specifies one or all senders) + default: + // restricted filter: do not return any events, + // even if other elements in filters array were not restricted). + // client should know better. + notice = "restricted: authenticated user does not have authorization for requested filters." return } } @@ -221,6 +226,8 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { advancedQuerier.BeforeQuery(filter) } + // TODO: Program calls SQL once for each filter in filters array. + // Maybe can replace with a single SQL query? events, err := store.QueryEvents(filter) if err != nil { s.Log.Errorf("store: %v", err) @@ -236,11 +243,11 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { for _, event := range events { ws.WriteJSON([]interface{}{"EVENT", id, event}) } - ws.WriteJSON([]interface{}{"EOSE", id}) } - + // moved EOSE out of for loop. + // otherwise subscriptions may be cancelled too early + ws.WriteJSON([]interface{}{"EOSE", id}) setListener(id, ws, filters) - break case "CLOSE": var id string json.Unmarshal(request[1], &id) @@ -250,7 +257,6 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { } removeListenerId(ws, id) - break case "AUTH": if auther, ok := s.relay.(Auther); ok { var evt nostr.Event @@ -271,7 +277,6 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { } else { notice = "unknown message type " + typ } - return } }(message) }