gwoe-antragspruefer/docs/adr/0005-keycloak-sso-with-dev-bypass.md
Dotty Dotter f0f1c39911 Docs: Feld-Mapping-Tabelle pro Adapter + ADR 0005 + Auth-Tests
Adapter-Capabilities-Matrix (#93) erweitert um detailliertes Feld-
Mapping: Pro Adapter welches API-/HTML-/JSON-Feld zu welchem
Drucksache-Feld wird (title, datum, fraktionen, drucksache, link, typ)
mit konkreten Beispielwerten. 12 Adapter-Sektionen.

ADR 0005: Keycloak SSO mit Dev-Bypass — dokumentiert die Entscheidung
für Read/Write-Trennung (GET offen, POST mit JWT) und den Dev-Modus
(Auth deaktiviert wenn KEYCLOAK_URL nicht gesetzt).

Auth-Tests: 7 neue Tests für Token-Extraction, Auth-Enabled-Detection,
_pick_best_title (letztere skipped wenn slowapi nicht installiert).

201 passed, 5 skipped.
2026-04-10 16:29:28 +02:00

2.8 KiB

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.