Files
svc-essensplanung/Doku/adr/003-single-user-mit-token.md
jensandClaude Opus 4.8 cb3cbfb394 M0: Skelett + Auth-Grundgerüst (Keycloak-OIDC + API-Token)
- Symfony 7.4 LTS, PHP 8.4, FrankenPHP, SQLite (3-Layer src/UI|Logic|Data)
- Auth: manueller OidcClient (Authorization-Code) im UI-Layer, kein
  Security-Bundle/league; Session-Gate via SessionAuthSubscriber
- API-Guard via statischem X-Api-Token (ApiTokenSubscriber); ExceptionSubscriber
- UserEntity (Auto-Provision) + Init-Migration
- Docker (php:8.4-frankenphp) + compose (essen.ljh31.de, traefik-net external)
- SmokeTests (7) grün: Redirect-Fälle, API-Token, Auth-Render, Logout

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-13 22:48:24 +02:00

36 lines
1.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 003 – Auth: Keycloak-OIDC (Web) + statischer API-Token (HA)
**Status:** accepted (überarbeitet 2026-09-13; ersetzt „kein Login")
**Kontext.** Das Werkzeug wird im privaten Homelab von **einer** Person (bzw.
Familie via LAN) genutzt. Es gibt bereits eine Keycloak-Instanz
(`https://iam.ljh31.de`, Realm `family`), die von `open-webui`/`webuix` genutzt
wird – eine Wiederverwendung ist kostenlos. Home-Assistant soll zusätzlich die
API (`GET /api/today`) konsumieren; ein zweiter, stateless Auth-Mechanismus ist
für Consumer wie HA robuster als eine Browser-Session.
**Entscheidung.**
1. **Web-UI:** Keycloak-OIDC (Authorization-Code) gegen Realm `family`,
eigener Client `essens` (Redirect `https://essen.ljh31.de/auth/callback`).
Verifiziert wird das Id-Token (RS256 + JWKS); pro Login wird eine lokale
User-Zeile auto-provisioniert (`essens_user`, gekoppelt an `sub`).
Die App selbst ist ein einfaches **Session-Auth-Gate**
(`SessionAuthSubscriber`): Session-Key `auth_sub` fehlt → Redirect `/login`.
Kein Symfony-Security-Authenticator, keine Rollen.
2. **API:** optionaler statischer Token per Header `X-Api-Token`
(env `API_TOKEN`), geprüft durch `ApiTokenSubscriber` (nur `/api/*`).
Token leer/leer-String → API blockiert; HA bekommt den Token direkt
(kein Keycloak-Refresh-Flow im Consumer).
**Konsequenzen.**
- + Wiederverwendung vorhandener IdP, keine zweite Auth-Welt.
- + HA-Integration bleibt trivial (ein Header statt OIDC im Sensor).
- − Manueller OIDC-Client (JWKS/Id-Token) statt Framework-Lib – bewusst:
kein `league/oauth2-client`/Security-Bundle im Stack, Code bleibt klein
und auditierbar.
- − Zwei Auth-Pfade (Session + Token) – klar getrennt nach Pfad-/Header-Gate.
**Abgelöst.** Fassung „Single-User, keine Authentifizierung" (M0-Start) –
Login via eigener Domain ohne Identität war mit HA-Kopplung und
Familien-Nutzung nicht mehr akzeptabel.