clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/standalone-relay
tinyrelay / tinyclient / remote_auth_test.go
remote_auth_test.go 2.4K
1package tinyclient23import (4 "net/http"5 "net/http/httptest"6 "strings"7 "testing"8)910func TestRemoteRejectsWrongPublicHostBeforeForwarding(t *testing.T) {11 upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Error("forwarded request for a foreign public host") }))12 defer upstream.Close()13 remote, err := NewRemote(RemoteOptions{BackendURL: upstream.URL, PublicURL: "http://relay.example"})14 if err != nil {15 t.Fatal(err)16 }17 request := httptest.NewRequest("POST", "http://attacker.example/session", nil)18 request.Header.Set("Authorization", "Nostr exact-proof")19 response := httptest.NewRecorder()20 remote.ServeHTTP(response, request)21 if response.Code != http.StatusMisdirectedRequest {22 t.Fatalf("foreign host accepted: %d", response.Code)23 }24}2526func TestBackendContractNeverTrustsCallerPubkeysOrWrites(t *testing.T) {27 owner := strings.Repeat("a", 64)28 backend := &fakeBackend{policy: DefaultPolicy(owner)}29 app, err := New(backend, Options{Actor: func(r *http.Request) (string, error) {30 cookie, err := r.Cookie("tiny_session")31 if err == nil && cookie.Value == "valid-session" {32 return owner, nil33 }34 return "", nil35 }})36 if err != nil {37 t.Fatal(err)38 }39 for _, authenticated := range []bool{false, true} {40 req := httptest.NewRequest("GET", BackendPath+"?method=browserepos&actor="+owner, nil)41 req.Header.Set("X-Actor", owner)42 if authenticated {43 req.AddCookie(&http.Cookie{Name: "tiny_session", Value: "valid-session"})44 }45 response := httptest.NewRecorder()46 app.BackendHandler().ServeHTTP(response, req)47 want := "browserepos:"48 if authenticated {49 want += owner50 }51 if response.Code != 200 || backend.call != want {52 t.Fatalf("actor trusted incorrectly: %d call=%s", response.Code, backend.call)53 }54 }55 for _, tc := range []struct {56 method, path string57 status int58 }{59 {"GET", BackendPath + "?method=setpolicy", 400},60 {"POST", BackendPath + "?method=browserepos", 405},61 {"GET", BackendPath + "?method=browserepos&params=invalid", 400},62 } {63 backend.call = ""64 req := httptest.NewRequest(tc.method, tc.path, nil)65 req.AddCookie(&http.Cookie{Name: "tiny_session", Value: "valid-session"})66 response := httptest.NewRecorder()67 app.BackendHandler().ServeHTTP(response, req)68 if response.Code != tc.status || backend.call != "" {69 t.Fatalf("unsafe query: %d call=%s", response.Code, backend.call)70 }71 }72}