Files
pixa/internal/session/session_cookie_attributes_test.go
sneak cb9e14eee7
All checks were successful
check / check (push) Successful in 1m48s
refactor: drop the ignored secure toggle parameter from session.NewManager
Per review on PR #48: pre-1.0 there is no installed base to keep
compiling against, so remove the dead parameter in one pass instead of
deferring. NewManager now takes only the signing key. Update the
handlers.go call site and its stale comment, mechanically update the
NewManager call shapes in the session tests (assertions unchanged),
collapse the now-meaningless constructor-argument loop in the cookie
attributes test, and drop the moot P1 Future Step from TODO.md.

Reviewer-directed test call-site updates; cookie behavior is unchanged
from the previous commit (always Secure/HttpOnly/SameSite=Strict).
2026-08-07 22:24:15 +07:00

83 lines
2.2 KiB
Go

package session
import (
"net/http"
"net/http/httptest"
"testing"
)
// TestSessionCookieAttributesAlwaysSecure verifies that every cookie
// emitted by the session manager carries HttpOnly, Secure, and a
// SameSite mode of Lax or stricter. Session cookies contain the
// authentication state and must never be exposed to script (HttpOnly),
// sent over plaintext HTTP (Secure), or attached to cross-site
// requests (SameSite). Nothing may weaken these attributes.
//
// This covers both cookie-writing paths: CreateSession (the login
// set-cookie path) and ClearSession (the logout delete-cookie path).
func TestSessionCookieAttributesAlwaysSecure(t *testing.T) {
mgr, err := NewManager("test-signing-key-12345")
if err != nil {
t.Fatalf("NewManager() error = %v", err)
}
writePaths := []struct {
name string
setCookie func(t *testing.T, w http.ResponseWriter)
}{
{
name: "CreateSession",
setCookie: func(t *testing.T, w http.ResponseWriter) {
t.Helper()
if err := mgr.CreateSession(w); err != nil {
t.Fatalf("CreateSession() error = %v", err)
}
},
},
{
name: "ClearSession",
setCookie: func(t *testing.T, w http.ResponseWriter) {
t.Helper()
mgr.ClearSession(w)
},
},
}
for _, writePath := range writePaths {
t.Run(writePath.name, func(t *testing.T) {
w := httptest.NewRecorder()
writePath.setCookie(t, w)
var sessionCookie *http.Cookie
for _, c := range w.Result().Cookies() {
if c.Name == CookieName {
sessionCookie = c
break
}
}
if sessionCookie == nil {
t.Fatalf("no cookie named %q was set", CookieName)
}
t.Logf("cookie attributes: HttpOnly=%v Secure=%v SameSite=%v",
sessionCookie.HttpOnly, sessionCookie.Secure, sessionCookie.SameSite)
if !sessionCookie.HttpOnly {
t.Error("session cookie must have HttpOnly set")
}
if !sessionCookie.Secure {
t.Error("session cookie must have Secure set")
}
if sessionCookie.SameSite != http.SameSiteLaxMode &&
sessionCookie.SameSite != http.SameSiteStrictMode {
t.Errorf("session cookie SameSite = %v, want Lax (%v) or Strict (%v)",
sessionCookie.SameSite, http.SameSiteLaxMode, http.SameSiteStrictMode)
}
})
}
}