50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
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:]
|
|
}
|