package auth import ( "net/http" "net/http/httptest" "strings" "testing" "time" ) func TestManagerRejectsTamperedAndExpiredCookies(t *testing.T) { manager := NewManager([]byte(strings.Repeat("s", 32)), true) request := httptest.NewRequest(http.MethodGet, "/login", nil) response := httptest.NewRecorder() csrf, authenticated := manager.Ensure(response, request) if csrf == "" || authenticated { t.Fatalf("Ensure = (%q, %t), want anonymous CSRF session", csrf, authenticated) } cookie := response.Result().Cookies()[0] if !cookie.HttpOnly || !cookie.Secure || cookie.SameSite != http.SameSiteLaxMode || cookie.Path != "/" { t.Fatalf("session cookie is missing security attributes: %#v", cookie) } tampered := *cookie tampered.Value = flipCookieValue(t, cookie.Value) tamperedRequest := httptest.NewRequest(http.MethodPost, "/login", nil) tamperedRequest.AddCookie(&tampered) if _, ok := manager.VerifyCSRF(tamperedRequest, csrf); ok { t.Fatal("tampered signed cookie passed CSRF verification") } manager.now = func() time.Time { return time.Now().Add(9 * time.Hour) } expiredRequest := httptest.NewRequest(http.MethodPost, "/login", nil) expiredRequest.AddCookie(cookie) if _, ok := manager.VerifyCSRF(expiredRequest, csrf); ok { t.Fatal("expired cookie passed CSRF verification") } } func flipCookieValue(t *testing.T, value string) string { t.Helper() if value == "" { t.Fatal("cannot tamper with an empty cookie") } if value[0] == 'A' { return "B" + value[1:] } return "A" + value[1:] }