package authn import ( "testing" "sourcecraft.dev/bigbes/sr-ht-core/crypto" ) func TestUsernameFromRequest_ValidCookieRoundTrips(t *testing.T) { got := UsernameFromRequest(request(sealCookie(t, "bigbes"), nil)) if got != "bigbes" { t.Fatalf("username = %q, want %q", got, "bigbes") } } func TestUsernameFromRequest_StripsTilde(t *testing.T) { got := UsernameFromRequest(request(sealCookie(t, "~bigbes"), nil)) if got != "bigbes" { t.Fatalf("username = %q, want %q", got, "bigbes") } } // A cookie whose ciphertext has been altered must fail the Fernet HMAC and read // as anonymous — not as an error, and certainly not as an identity. func TestUsernameFromRequest_TamperedCookieIsAnonymous(t *testing.T) { got := UsernameFromRequest(request(tamper(t, sealCookie(t, "bigbes")), nil)) if got != "" { t.Fatalf("tampered cookie yielded %q, want anonymous", got) } } func TestUsernameFromRequest_AbsentCookieIsAnonymous(t *testing.T) { if got := UsernameFromRequest(request("", nil)); got != "" { t.Fatalf("absent cookie yielded %q, want anonymous", got) } } func TestUsernameFromRequest_GarbageIsAnonymous(t *testing.T) { for name, value := range map[string]string{ "not base64": "not-a-valid-fernet-token", "empty": "", "truncated fernet": sealCookie(t, "bigbes")[:10], } { t.Run(name, func(t *testing.T) { if got := UsernameFromCookie(value); got != "" { t.Fatalf("garbage cookie yielded %q, want anonymous", got) } }) } } // A cookie sealed under a key we no longer hold — the shape of both a rotated // network key and an outright forgery. It must expire the session, not the // request. func TestUsernameFromCookie_ForeignKeyIsAnonymous(t *testing.T) { value := sealCookieWithKey(t, &rotatedKey, "bigbes") if got := UsernameFromCookie(value); got != "" { t.Fatalf("cookie under a foreign key yielded %q, want anonymous", got) } // Sanity: the same payload under the live key does resolve, so the test // above is proving the key check and not a broken helper. if got := UsernameFromCookie(sealCookie(t, "bigbes")); got != "bigbes" { t.Fatalf("control cookie yielded %q, want %q", got, "bigbes") } } func TestUsernameFromCookie_NonJSONPayloadIsAnonymous(t *testing.T) { value := string(crypto.Encrypt([]byte("plain text, well sealed"))) if got := UsernameFromCookie(value); got != "" { t.Fatalf("non-JSON payload yielded %q, want anonymous", got) } } // A well-sealed cookie can still carry a name we must refuse to treat as an // identity: empty, or something that would not survive being used as a path // segment or a log field. func TestUsernameFromCookie_UnusableNameIsAnonymous(t *testing.T) { for _, name := range []string{ "", "..", "../../etc/passwd", "has space", "Uppercase", "-leading-dash", } { t.Run(name, func(t *testing.T) { if got := UsernameFromCookie(sealCookie(t, name)); got != "" { t.Fatalf("cookie name %q yielded %q, want anonymous", name, got) } }) } }