Files
headquarter/openspec/changes/simplify-authentik-auth/design.md
T
Fusion 2ce7862058 feat: simplify auth flow - replace JWT with session cookies
Replace complex JWT + refresh token authentication with simple
session-based auth using signed cookies.

**Removed:**
- JWT token service (jwt_service.py)
- Refresh token store (refresh_store.py)
- Refresh token model and database table
- JWKS fetching and OIDC token verification
- python-jose dependency

**Added:**
- Session service (session.py) with HMAC-SHA256 signed cookies
- Auth dependencies module for shared auth logic
- Session-based auth endpoints

**Updated:**
- All API endpoints to use session-based auth
- Config: removed JWT settings, added SESSION_SECRET/SESSION_TTL_HOURS
- Tests: rewritten for session-based flow
- Frontend: no changes needed (already uses cookies)

Quality gates: ruff ✓, mypy ✓, typecheck ✓, lint ✓
2026-05-18 22:54:53 +02:00

2.8 KiB

Simplified Authentik Auth Flow - Design

Architecture

User → Frontend → Authentik (OAuth2) → Backend (Session) → Protected Resources

Authentication Flow

1. Login Initiation

GET /auth/login
→ Redirect to Authentik OAuth authorize URL
→ State parameter stored in cookie (auth_state)

2. OAuth Callback

GET /auth/callback?code=...&state=...
→ Verify state parameter
→ Exchange code for access token with Authentik
→ Fetch user info from Authentik /userinfo endpoint
→ Create/update user in local database
→ Create session cookie (signed, httpOnly)
→ Redirect to frontend

3. Authenticated Requests

Request with session cookie
→ Verify session signature
→ Load user from database
→ Attach user to request context

4. Logout

GET /auth/logout
→ Delete session cookie
→ Optionally revoke token at Authentik
→ Redirect to frontend

Session Management

  • Name: session
  • Value: Signed cookie containing user_id
  • Properties: httpOnly, Secure (production), SameSite=Lax
  • Expiry: Browser session or configurable duration

Session Store

  • In-memory or Redis (configurable)
  • Maps session_id → user_id + expiry
  • Simple cleanup on expiry

User Sync

On each login:

  1. Fetch user info from Authentik /application/o/userinfo/
  2. Update local user record:
    • email
    • name
    • authentik_id
    • groups (for future team feature)
  3. Create user if not exists

API Changes

Removed Endpoints

  • POST /auth/refresh - No refresh tokens needed

Modified Endpoints

  • GET /auth/login - Simpler, no nonce needed
  • GET /auth/callback - No JWT minting, just session creation
  • GET /auth/me - Return user from session instead of JWT
  • POST /auth/logout - Just clear session cookie

New Endpoints

  • None (simplification!)

Middleware Changes

Current (to be removed)

  • JWT decoding
  • Token expiry checking
  • Refresh token validation

New

  • Session cookie parsing
  • Signature verification
  • User loading from database

Database Changes

Remove Tables

  • refresh_tokens - No longer needed

Keep Tables

  • users - Still needed for local user data
  • user_configs - User preferences

Configuration Changes

Removed

  • JWT_SECRET
  • JWT_ALGORITHM
  • ACCESS_TOKEN_TTL_MINUTES
  • REFRESH_TOKEN_TTL_DAYS

Modified

  • AUTHENTIK_AUDIENCE - May not be needed

Added

  • SESSION_SECRET - For signing session cookies
  • SESSION_TTL_HOURS - Session duration (default: 24)
  • SESSION_STORE - "memory" or "redis"

Implementation Order

  1. Create session management module
  2. Simplify auth endpoints
  3. Update auth middleware
  4. Remove JWT and refresh token code
  5. Update frontend auth handling
  6. Update configuration
  7. Tests