ultisuite-backend/internal/api/auth/handlers_test.go
R3D347HR4Y 525edb188a
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(authentik): enhance OIDC flow with new logout redirect and branding support
- Added a new blueprint for OIDC logout that invalidates the Authentik session and redirects to a specified landing page.
- Introduced custom CSS and JS files for branding, improving the visual integration of Authentik flows.
- Updated Nginx configuration to serve the new branding assets and handle specific routes for signup and password recovery.
- Enhanced the flow completion logic to support OIDC bridge functionality, including session management and redirect handling.
- Implemented unit tests for the new OIDC bridge and flow context functionalities to ensure reliability.
2026-06-21 00:12:53 +02:00

101 lines
2.9 KiB
Go

package authapi
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
)
func TestValidateFlowSlugAllowed(t *testing.T) {
t.Parallel()
for _, slug := range []string{FlowEnrollment, FlowRecovery, FlowAuthentication} {
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/flows/"+slug+"/start", nil)
got, ok := validateFlowSlug(rec, req, slug)
if !ok || got != slug {
t.Fatalf("slug %q: ok=%v got=%q code=%d", slug, ok, got, rec.Code)
}
}
}
func TestValidateFlowSlugRejected(t *testing.T) {
t.Parallel()
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/flows/default-invalidation-flow/start", nil)
_, ok := validateFlowSlug(rec, req, "default-invalidation-flow")
if ok {
t.Fatal("expected slug to be rejected")
}
if rec.Code != http.StatusNotFound {
t.Fatalf("status = %d", rec.Code)
}
}
func TestRespondFlowMissingCookie(t *testing.T) {
t.Parallel()
h := NewHandler("http://127.0.0.1:1", "http://localhost:3004", "", "", "", nil)
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/flows/ulti-enrollment/respond", bytes.NewReader([]byte(`{"payload":{"component":"x"}}`)))
rctx := chi.NewRouteContext()
rctx.URLParams.Add("slug", FlowEnrollment)
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
h.RespondFlow(rec, req)
if rec.Code != http.StatusUnauthorized {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
}
func TestBuildLoginRedirectURL(t *testing.T) {
t.Parallel()
got := buildLoginRedirectURL("http://localhost:3004", "/mail/inbox")
want := "http://localhost:3004/api/auth/login?bridge=1&returnTo=%2Fmail%2Finbox"
if got != want {
t.Fatalf("got %q want %q", got, want)
}
}
func TestBuildOIDCBridgeConfig(t *testing.T) {
t.Parallel()
cfg := buildOIDCBridgeConfig(
"http://nginx/auth/application/o/ulti/",
"ulti-backend",
"changeme",
"https://dev.ultispace.fr/mail",
"http://authentik-server:9000",
)
if cfg.redirectURI != "https://dev.ultispace.fr/api/auth/callback" {
t.Fatalf("redirectURI = %q", cfg.redirectURI)
}
if cfg.authorizeURL != "http://authentik-server:9000/auth/application/o/authorize/" {
t.Fatalf("authorizeURL = %q", cfg.authorizeURL)
}
}
func TestBuildLoginRedirectURLStripsMailPrefix(t *testing.T) {
t.Parallel()
got := buildLoginRedirectURL("https://dev.ultispace.fr/mail", "/mail/inbox")
want := "https://dev.ultispace.fr/api/auth/login?bridge=1&returnTo=%2Fmail%2Finbox"
if got != want {
t.Fatalf("got %q want %q", got, want)
}
}
func TestFlowRateLimiterMemory(t *testing.T) {
t.Parallel()
lim := NewFlowRateLimiter(nil)
req := httptest.NewRequest(http.MethodPost, "/start", nil)
req.RemoteAddr = "203.0.113.1:1234"
for i := 0; i < flowRateLimitMax; i++ {
if !lim.Allow(req) {
t.Fatalf("attempt %d should be allowed", i+1)
}
}
if lim.Allow(req) {
t.Fatal("expected rate limit block")
}
}