package httpx_test import ( "net/http/httptest" "testing" "git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/httpx" ) func TestSignerRoundTripAndTamper(t *testing.T) { s, err := httpx.NewSigner([]byte("a-signing-key-0123456789abcdef")) if err != nil { t.Fatalf("NewSigner: %v", err) } if _, err := httpx.NewSigner(nil); err == nil { t.Error("NewSigner(nil) = nil, want an error (fail closed)") } const value = "hello.world/with/slashes" tok := s.Sign(value) got, ok := s.Unsign(tok) if !ok || got != value { t.Fatalf("Unsign(Sign(%q)) = %q,%v", value, got, ok) } if _, ok := s.Unsign(tok + "x"); ok { t.Error("Unsign accepted a tampered token") } if _, ok := s.Unsign("not-a-token"); ok { t.Error("Unsign accepted a malformed token") } // A different key must not validate the token. other, _ := httpx.NewSigner([]byte("another-key-0123456789abcdefgh")) if _, ok := other.Unsign(tok); ok { t.Error("a token validated under a different key") } } func TestPreSessionCSRFEnsureAndValid(t *testing.T) { p, err := httpx.NewPreSessionCSRF([]byte("a-cookie-secret-0123456789abcdef")) if err != nil { t.Fatalf("NewPreSessionCSRF: %v", err) } rec := httptest.NewRecorder() r := httptest.NewRequest("GET", "/someguid", nil) tok, err := p.Ensure(rec, r) if err != nil { t.Fatalf("Ensure: %v", err) } cookies := rec.Result().Cookies() if len(cookies) != 1 || cookies[0].Name != httpx.PreSessionCookieName { t.Fatalf("Ensure cookies = %v, want one %s", cookies, httpx.PreSessionCookieName) } if !cookies[0].HttpOnly { t.Error("the pre-session CSRF cookie is not HttpOnly") } // Double-submit: cookie value must equal the submitted token. r2 := httptest.NewRequest("POST", "/someguid?do=auth&action=enroll.begin", nil) r2.AddCookie(cookies[0]) if !p.Valid(r2, tok) { t.Error("Valid rejected a matching double-submit token") } if p.Valid(r2, tok+"x") { t.Error("Valid accepted a mismatched token") } if p.Valid(httptest.NewRequest("POST", "/", nil), tok) { t.Error("Valid accepted a token with no cookie") } if p.Valid(r2, "") { t.Error("Valid accepted an empty token") } // Ensure reuses a valid cookie rather than rotating it every call. rec2 := httptest.NewRecorder() tok2, err := p.Ensure(rec2, r2) if err != nil { t.Fatalf("Ensure(reuse): %v", err) } if tok2 != tok { t.Error("Ensure rotated an already-valid token") } if len(rec2.Result().Cookies()) != 0 { t.Error("Ensure re-issued a cookie for a valid token") } }