package auth import ( "net/http" "net/http/httptest" "testing" "time" ) func testManager(t *testing.T) *Manager { t.Helper() m, err := New([]byte("0123456789abcdef0123456789abcdef"), time.Hour, false, "sam", "", "hunter2") if err != nil { t.Fatalf("New: %v", err) } return m } func TestCredentials(t *testing.T) { m := testManager(t) if !m.CheckCredentials("sam", "hunter2") { t.Error("valid credentials rejected") } if m.CheckCredentials("sam", "wrong") { t.Error("wrong password accepted") } if m.CheckCredentials("finn", "hunter2") { t.Error("wrong username accepted") } } func TestSessionRoundTripAndTamper(t *testing.T) { m := testManager(t) rec := httptest.NewRecorder() m.Issue(rec) res := rec.Result() req := httptest.NewRequest(http.MethodGet, "/", nil) for _, c := range res.Cookies() { req.AddCookie(c) } if !m.Authenticated(req) { t.Fatal("issued session is not authenticated") } // Tamper with the session value: the HMAC must reject it. tampered := httptest.NewRequest(http.MethodGet, "/", nil) for _, c := range res.Cookies() { if c.Name == sessionCookie { c.Value = c.Value[:len(c.Value)-2] + "xx" } tampered.AddCookie(c) } if m.Authenticated(tampered) { t.Fatal("tampered session accepted") } } func TestCSRF(t *testing.T) { m := testManager(t) rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/login", nil) token := m.EnsureCSRF(rec, req) if token == "" { t.Fatal("empty csrf token") } // The token is delivered as a cookie; a matching form value passes. form := httptest.NewRequest(http.MethodPost, "/login", nil) form.PostForm = map[string][]string{"csrf": {token}} for _, c := range rec.Result().Cookies() { form.AddCookie(c) } if !m.CheckCSRF(form) { t.Error("matching csrf rejected") } // A different form value fails. bad := httptest.NewRequest(http.MethodPost, "/login", nil) bad.PostForm = map[string][]string{"csrf": {"not-the-token"}} for _, c := range rec.Result().Cookies() { bad.AddCookie(c) } if m.CheckCSRF(bad) { t.Error("mismatched csrf accepted") } // No cookie at all fails. none := httptest.NewRequest(http.MethodPost, "/login", nil) none.PostForm = map[string][]string{"csrf": {token}} if m.CheckCSRF(none) { t.Error("csrf accepted without cookie") } } func TestExpiredSession(t *testing.T) { m, err := New([]byte("0123456789abcdef0123456789abcdef"), -time.Minute, false, "sam", "", "hunter2") if err != nil { t.Fatalf("New: %v", err) } rec := httptest.NewRecorder() m.Issue(rec) req := httptest.NewRequest(http.MethodGet, "/", nil) for _, c := range rec.Result().Cookies() { req.AddCookie(c) } if m.Authenticated(req) { t.Error("expired session accepted") } }