session.idle_timeout (minutes, default 15) joins the app-config registry and drives the onboarding Garmin session eviction, distinct from session.duration (the login cookie lifetime in hours). The raw Keycloak ID token no longer rides in auth.Claims through every request context: it's minted into the session cookie separately and read back only by the logout handler via IDTokenFromSessionCookie. OnboardingWizard uses the type-imported FormEvent<HTMLFormElement> instead of the React.FormEvent namespace alias. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
package auth
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func protectedTestHandler() http.Handler {
|
|
return RequireSession([]byte(testSecret))(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
claims, ok := ClaimsFromContext(r.Context())
|
|
if !ok {
|
|
http.Error(w, "no claims in context", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Write([]byte(claims.Name))
|
|
}))
|
|
}
|
|
|
|
func TestRequireSession_NoCookie(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
rec := httptest.NewRecorder()
|
|
protectedTestHandler().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Fatalf("status = %d, want 401", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestRequireSession_ValidCookie(t *testing.T) {
|
|
cookie, err := MintSessionCookie(Claims{Sub: "u1", Name: "Alice", Email: "alice@example.com"}, "", []byte(testSecret), time.Hour, false)
|
|
if err != nil {
|
|
t.Fatalf("mint: %v", err)
|
|
}
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.AddCookie(cookie)
|
|
rec := httptest.NewRecorder()
|
|
protectedTestHandler().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200, body = %s", rec.Code, rec.Body.String())
|
|
}
|
|
if rec.Body.String() != "Alice" {
|
|
t.Fatalf("body = %q, want Alice", rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRequireSession_ExpiredCookie(t *testing.T) {
|
|
cookie, err := MintSessionCookie(Claims{Sub: "u1"}, "", []byte(testSecret), -time.Hour, false)
|
|
if err != nil {
|
|
t.Fatalf("mint: %v", err)
|
|
}
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.AddCookie(cookie)
|
|
rec := httptest.NewRecorder()
|
|
protectedTestHandler().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Fatalf("status = %d, want 401", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestRequireSession_TamperedCookie(t *testing.T) {
|
|
cookie, err := MintSessionCookie(Claims{Sub: "u1"}, "", []byte(testSecret), time.Hour, false)
|
|
if err != nil {
|
|
t.Fatalf("mint: %v", err)
|
|
}
|
|
cookie.Value = flipSignatureChar(cookie.Value)
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.AddCookie(cookie)
|
|
rec := httptest.NewRecorder()
|
|
protectedTestHandler().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Fatalf("status = %d, want 401", rec.Code)
|
|
}
|
|
}
|