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>
This commit is contained in:
@@ -1,20 +1,35 @@
|
||||
# 003 – Single-User, keine Authentifizierung
|
||||
# 003 – Auth: Keycloak-OIDC (Web) + statischer API-Token (HA)
|
||||
|
||||
**Status:** accepted
|
||||
**Status:** accepted (überarbeitet 2026-09-13; ersetzt „kein Login")
|
||||
|
||||
**Kontext.** Das Werkzeug wird im privaten Homelab von **einer** Person (bzw.
|
||||
Familie via LAN) genutzt. Ein Login-Flow wird zur Barriere, nicht zum Feature.
|
||||
Später soll Home-Assistant die API konsumieren, und dort ist es einfacher,
|
||||
einen Shared-Token zu haben statt ein OIDC-Realm zu betreiben.
|
||||
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.** Im MVP **kein Login**. Die API ist hinter dem bestehenden
|
||||
Traefik-Routing `essen.ljh31.de` (ACME/TLS) erreichbar; wer die Domain kennt,
|
||||
kann aufrufen. Optional (Phase 2): **Shared-API-Token** per Header
|
||||
(`X-Api-Token`) für externe Clients wie HA.
|
||||
**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.**
|
||||
- + Einfachster möglicher Pfad, kein Auth-State, kein JWT.
|
||||
- + HA-Integration ist trivial (einfacher Token statt OIDC).
|
||||
- − Kein Benutzer-Abgrenzen, keine Rechte. Im aktuellen Kontext kein Risiko
|
||||
(LAN + eigene Domain).
|
||||
- − Wenn es irgendwann öffentliches Hosting wird, ADR-003 ersetzen.
|
||||
- + 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.
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ Wenn sich etwas ändert: **neue** ADR, alte als `superseded` markieren.
|
||||
|----|-------|--------|
|
||||
| [001](001-backend-symfony.md) | Backend auf Symfony 7 (PHP) | accepted |
|
||||
| [002](002-frontend-htmx.md) | Frontend: serverseitig + htmx (kein React) | accepted |
|
||||
| [003](003-single-user-mit-token.md) | Single-User, keine Authentifizierung (+ optionales API-Token) | accepted |
|
||||
| [003](003-single-user-mit-token.md) | Auth: Keycloak-OIDC (Web) + statischer API-Token (HA) | accepted |
|
||||
| [004](004-ha-consumer.md) | Home-Assistant als Consumer, nicht als Host | accepted |
|
||||
| [005](005-sqlite.md) | SQLite als Datenbank (vorerst) | accepted |
|
||||
| [006](006-inspiration-algorithmus.md) | Inspiration-Algorithmus: gewichteter Mix | proposed |
|
||||
|
||||
Reference in New Issue
Block a user