package auth import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "github.com/golang-jwt/jwt/v5" ) func TestAuthenticateAcceptsValidatedOIDCSessionCookie(t *testing.T) { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatal(err) } var issuer string issuerServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/.well-known/openid-configuration": _ = json.NewEncoder(w).Encode(map[string]any{"issuer": issuer, "jwks_uri": issuer + "/jwks"}) case "/jwks": _ = json.NewEncoder(w).Encode(map[string]any{"keys": []any{ecJWK("ec-key", &key.PublicKey)}}) default: http.NotFound(w, r) } })) defer issuerServer.Close() issuer = issuerServer.URL verifier, err := NewOIDCVerifier(OIDCConfig{ Issuer: issuer, Audience: "gateway-api", TenantID: "tenant-1", RolePrefix: "gateway.", RequiredScopes: []string{"gateway.access"}, HTTPClient: issuerServer.Client(), }) if err != nil { t.Fatal(err) } authenticator := New("local-jwt-secret", "", "") authenticator.OIDCVerifier = verifier raw := signedOIDCToken(t, issuer, "ec-key", jwt.SigningMethodES256, key, nil) request := httptest.NewRequest(http.MethodGet, "/api/v1/me", nil) request.AddCookie(&http.Cookie{Name: OIDCSessionCookieName, Value: raw}) user, err := authenticator.Authenticate(request) if err != nil { t.Fatalf("authenticate OIDC session cookie: %v", err) } if user.ID != "platform-subject" || user.Source != "oidc" { t.Fatalf("unexpected session user: %#v", user) } if user.TokenExpiresAt.Before(time.Now().Add(50 * time.Minute)) { t.Fatalf("token expiry was not retained: %v", user.TokenExpiresAt) } } func TestAuthenticateBearerTakesPrecedenceOverOIDCSessionCookie(t *testing.T) { authenticator := New("local-jwt-secret", "", "") localToken, err := authenticator.SignJWT(&User{ID: "local-user", Source: "gateway", Roles: []string{"user"}}, time.Hour) if err != nil { t.Fatal(err) } request := httptest.NewRequest(http.MethodGet, "/api/v1/me", nil) request.Header.Set("Authorization", "Bearer "+localToken) request.AddCookie(&http.Cookie{Name: OIDCSessionCookieName, Value: "not-a-token"}) user, err := authenticator.Authenticate(request) if err != nil { t.Fatalf("authenticate bearer token: %v", err) } if user.ID != "local-user" || user.Source != "gateway" { t.Fatalf("cookie overrode explicit bearer credentials: %#v", user) } } func TestAuthenticateRejectsInvalidOIDCSessionCookie(t *testing.T) { authenticator := New("local-jwt-secret", "", "") request := httptest.NewRequest(http.MethodGet, "/api/v1/me", nil) request.AddCookie(&http.Cookie{Name: OIDCSessionCookieName, Value: "not-a-token"}) if _, err := authenticator.Authenticate(request); err == nil { t.Fatal("invalid OIDC session cookie was accepted") } }