auth: clear session cookie under both host-only and parent-domain scope
Logout emitted a single Set-Cookie scoped to the configured cookie domain (parodia.dev). A browser holding the session under the older host-only scope (news.parodia.dev, from before the cookie domain widened for the games site) was never cleared, so logout looked like a no-op and stranded the user on a stale session logout couldn't reach. Clear both scopes. Also surface the who-page owner unlock's previously-silent misses: a genuine lookup/decode error, and a signed-in session that carries no username. Both used to fail with err discarded and no log, making a stuck owner undiagnosable.
This commit is contained in:
@@ -8,6 +8,56 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// TestClearCookieClearsBothScopes: when a parent cookie domain is configured,
|
||||
// clearCookie must emit a delete for BOTH the parent-domain scope and the
|
||||
// host-only scope. A browser holding a session under the older host-only scope
|
||||
// (from before the cookie domain widened for the games site) would otherwise
|
||||
// survive logout and keep the user signed in with a session logout can't reach.
|
||||
func TestClearCookieClearsBothScopes(t *testing.T) {
|
||||
a := &Authenticator{domain: "parodia.dev"}
|
||||
rec := httptest.NewRecorder()
|
||||
a.clearCookie(rec, sessionCookie)
|
||||
|
||||
var hostOnly, scoped bool
|
||||
for _, c := range rec.Result().Cookies() {
|
||||
if c.Name != sessionCookie {
|
||||
continue
|
||||
}
|
||||
if c.MaxAge >= 0 {
|
||||
t.Errorf("clear cookie should expire the session, got MaxAge=%d", c.MaxAge)
|
||||
}
|
||||
switch c.Domain {
|
||||
case "":
|
||||
hostOnly = true
|
||||
case "parodia.dev":
|
||||
scoped = true
|
||||
default:
|
||||
t.Errorf("unexpected clear Domain %q", c.Domain)
|
||||
}
|
||||
}
|
||||
if !hostOnly {
|
||||
t.Error("missing host-only clear (no Domain) — stale host-only sessions stay stranded")
|
||||
}
|
||||
if !scoped {
|
||||
t.Error("missing parent-domain clear (Domain=parodia.dev)")
|
||||
}
|
||||
}
|
||||
|
||||
// With no cookie domain configured, only the host-only clear is emitted.
|
||||
func TestClearCookieHostOnlyWhenNoDomain(t *testing.T) {
|
||||
a := &Authenticator{}
|
||||
rec := httptest.NewRecorder()
|
||||
a.clearCookie(rec, sessionCookie)
|
||||
|
||||
got := rec.Result().Cookies()
|
||||
if len(got) != 1 {
|
||||
t.Fatalf("want exactly one clear cookie, got %d", len(got))
|
||||
}
|
||||
if got[0].Domain != "" {
|
||||
t.Errorf("want host-only clear, got Domain=%q", got[0].Domain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignVerifyRoundTrip(t *testing.T) {
|
||||
a := &Authenticator{secret: []byte("test-secret-key-at-least-16")}
|
||||
payload := []byte(`{"sub":"abc","exp":123}`)
|
||||
|
||||
Reference in New Issue
Block a user