# 0005 — Keycloak SSO mit Dev-Bypass für Read/Write-Trennung | | | |---|---| | **Status** | accepted | | **Datum** | 2026-04-10 | | **Refs** | Issue #43, Commit 7159240 + 303b30f, app/auth.py | ## Kontext Die Webapp soll öffentlich durchsuchbar sein (Assessments lesen, PDFs ansehen, Auswertungen), aber Analyse-Aktionen (Antrag bewerten, Programme indexieren) nur authentifizierten Nutzern erlauben. Der User betreibt bereits einen Keycloak-Server unter `sso.toppyr.de` mit Realm `collaboration`. ## Optionen ### Option A — Keycloak-only mit hartem 401 Alle POST-Endpoints erfordern JWT. Ohne Keycloak-Server läuft nichts. **Vorteile:** Klar, sicher. **Nachteile:** Lokale Entwicklung blockiert ohne Keycloak-Instanz. ### Option B — Dev-Bypass: Auth nur wenn ENV gesetzt Wenn `KEYCLOAK_URL` leer ist → ALLE Endpoints offen (Dev-Modus). Wenn gesetzt → POST-Endpoints erfordern JWT, GET bleibt offen. **Vorteile:** Lokale Dev ohne Keycloak. Prod sofort sicher per ENV. **Nachteile:** Versehentlich Prod ohne ENV = alles offen. ### Option C — API-Key statt Keycloak Einfacher API-Key-Header für POST-Endpoints. **Vorteile:** Zero-Dependency. **Nachteile:** Kein SSO, kein User-Identity, keine Gruppen/Rollen. ## Entscheidung **Option B.** Dev-Bypass ermöglicht reibungslose lokale Entwicklung und Batch-Skripte (die keinen JWT haben). Prod-Absicherung über die drei ENV-Vars in docker-compose.yml. Die Keycloak-Client-Registrierung in `sso.toppyr.de` ist ein einmaliger manueller Schritt. ## Implementation - `app/auth.py`: JWKS-Cache (1h TTL), `get_current_user` (optional), `require_auth` (pflicht), `keycloak_login_url` (für Browser-Redirect) - POST-Endpoints (`/analyze`, `/api/analyze-drucksache`, `/api/programme/index`): `user: dict = Depends(require_auth)` - GET-Endpoints: unverändert offen - Frontend: `initAuth()` prüft `/api/auth/me`, steuert "Jetzt prüfen"-Button (disabled + Tooltip wenn nicht eingeloggt) und "Anmelden"-Button im Header ## Konsequenzen ### Positiv - Read-Only für alle, Write nur mit Login — klare Trennung - Batch-Skripte und auto-Re-Analyse im Container laufen im Dev-Modus (KEYCLOAK_URL nicht gesetzt), keine Auth-Hürde für Maintenance - Keycloak-Rollen über `realm_access.roles` im JWT verfügbar für künftige Gruppen-Features (#94 Bookmarks/Kommentare) ### Negativ - Dev-Modus ist unsicher — wenn jemand KEYCLOAK_URL in Prod vergisst zu setzen, ist alles offen. Mitigation: Health-Endpoint oder Startup-Warning wenn ENV fehlt. - JWKS-Cache (1h) bedeutet: nach Key-Rotation dauert es bis zu 1h bis alte Tokens abgelehnt werden. Für dieses Projekt akzeptabel. ### Folgen für andere ADRs - #94 Bookmarks/Kommentare baut auf der User-Identity aus dem JWT auf (`sub`, `email`, `realm_access.roles`). - #95 Queuing könnte Auth-User priorisieren.