Migration This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs. Contact me

internal/authn/authn_test.go

main · 2.8 KB · 104 lines raw

1 package authn
2
3 import (
4 "net/http"
5 "net/http/httptest"
6 "testing"
7
8 "gsg/internal/session"
9 )
10
11 func TestSafeNext(t *testing.T) {
12 cases := []struct {
13 in, want string
14 }{
15 {"", "/"},
16 {"/", "/"},
17 {"/demo/", "/demo/"},
18 {"/share/new?x=1", "/share/new?x=1"},
19 {"//evil.example", "/"},
20 {"https://evil.example", "/"},
21 {"http://evil.example/path", "/"},
22 {"relative", "/"},
23 }
24 for _, tc := range cases {
25 if got := safeNext(tc.in); got != tc.want {
26 t.Errorf("safeNext(%q) = %q, want %q", tc.in, got, tc.want)
27 }
28 }
29 }
30
31 func TestLoginRequiresIdentityHeader(t *testing.T) {
32 h := testHandlers(t)
33 req := httptest.NewRequest("GET", "/auth/login", nil)
34 rec := httptest.NewRecorder()
35 h.Login.ServeHTTP(rec, req)
36
37 if rec.Code != http.StatusUnauthorized {
38 t.Fatalf("status = %d, want %d", rec.Code, http.StatusUnauthorized)
39 }
40 if cookies := rec.Result().Cookies(); len(cookies) != 0 {
41 t.Fatalf("unauthenticated login set cookies: %v", cookies)
42 }
43 }
44
45 func TestLoginIssuesCookieAndHonorsSafeNext(t *testing.T) {
46 h := testHandlers(t)
47 req := httptest.NewRequest("GET", "/auth/login?next=/demo/", nil)
48 req.Header.Set("X-Authentik-Username", "alice")
49 rec := httptest.NewRecorder()
50 h.Login.ServeHTTP(rec, req)
51
52 if rec.Code != http.StatusSeeOther {
53 t.Fatalf("status = %d, want %d", rec.Code, http.StatusSeeOther)
54 }
55 if got := rec.Header().Get("Location"); got != "/demo/" {
56 t.Fatalf("Location = %q, want /demo/", got)
57 }
58 cookies := rec.Result().Cookies()
59 if len(cookies) != 1 || cookies[0].Name != session.CookieName {
60 t.Fatalf("cookies = %v, want one %s cookie", cookies, session.CookieName)
61 }
62 }
63
64 func TestLoginRejectsOffsiteNext(t *testing.T) {
65 h := testHandlers(t)
66 req := httptest.NewRequest("GET", "/auth/login?next=https://evil.example/", nil)
67 req.Header.Set("X-Authentik-Username", "alice")
68 rec := httptest.NewRecorder()
69 h.Login.ServeHTTP(rec, req)
70
71 if got := rec.Header().Get("Location"); got != "/" {
72 t.Fatalf("Location = %q, want /", got)
73 }
74 }
75
76 func TestLogoutClearsCookie(t *testing.T) {
77 h := testHandlers(t)
78 req := httptest.NewRequest("GET", "/auth/logout", nil)
79 rec := httptest.NewRecorder()
80 h.Logout.ServeHTTP(rec, req)
81
82 if rec.Code != http.StatusSeeOther {
83 t.Fatalf("status = %d, want %d", rec.Code, http.StatusSeeOther)
84 }
85 if got := rec.Header().Get("Location"); got != "/" {
86 t.Fatalf("Location = %q, want /", got)
87 }
88 cookies := rec.Result().Cookies()
89 if len(cookies) != 1 || cookies[0].Name != session.CookieName {
90 t.Fatalf("cookies = %v, want one %s cookie", cookies, session.CookieName)
91 }
92 if cookies[0].MaxAge >= 0 {
93 t.Fatalf("logout cookie MaxAge = %d, want negative", cookies[0].MaxAge)
94 }
95 }
96
97 func testHandlers(t *testing.T) Handlers {
98 t.Helper()
99 h, err := NewHandlers(Config{Sessions: session.NewManager()})
100 if err != nil {
101 t.Fatalf("NewHandlers: %v", err)
102 }
103 return h
104 }