feat(auth): Forward-Auth via JWT-Cookie (YunoHost yunohost.portal)

Discovery zeigte: YunoHost reicht den Usernamen nicht als Header durch, sondern im
signierten Cookie "yunohost.portal" (JWT, Claim "user"). Die Forward-Auth liest jetzt
die Identitaet aus Header ODER Cookie - nur von der Proxy-Quell-IP akzeptiert.
HS256-Signaturpruefung optional via TRUSTED_AUTH_JWT_SECRET (stdlib hmac, kein Dep).

- config: trusted_auth_cookie / _cookie_claim / _jwt_secret
- nginx-Vorlage + deploy/README: keine Identitaets-Header-Zeile mehr noetig; SSO-Schutz
  der Subdomain ist Pflicht (sonst Spoofing)
- Tests: Cookie-Extraktion, Signaturpruefung, Proxy-IP-Trust

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-18 08:44:33 +02:00
commit 881a5ac2de
6 changed files with 169 additions and 27 deletions

View file

@ -38,18 +38,28 @@ eintragen, die `map $http_upgrade …` einmalig im http{}-Kontext anlegen, dann
`nginx -t && systemctl reload nginx`. Subdomain `va.linix.de` in YunoHost
anlegen (Let's Encrypt) und per SSO schützen (nur erlaubte Tester/Gruppe).
## 4. Discovery: richtigen Identitäts-Header bestimmen
**Hinter dem SSO** aufrufen (durchs SSO-Portal einloggen, dann diese URL). Da das
Gateway den SSO-Admin zu diesem Zeitpunkt noch nicht kennt (Henne-Ei), den Admin-Key
als Query mitgeben:
## 4. Identität: YunoHost liefert sie im Cookie (nicht als Header)
Discovery (`/api/admin/request-headers?key=<ADMIN_API_KEY>` hinter dem SSO) zeigt:
YunoHost reicht den Usernamen **nicht** als eigenen Header durch, sondern im **JWT-Cookie
`yunohost.portal`** (Claim `user`). Das Gateway liest diesen Cookie direkt — daher:
```ini
# .env auf der GPU-Box:
TRUSTED_AUTH_COOKIE=yunohost.portal
TRUSTED_AUTH_COOKIE_CLAIM=user
TRUSTED_PROXY_IPS=<LAN-IP des YunoHost-Servers>
# optional (Härtung): HS256-Secret des Portals -> Signaturpruefung
# TRUSTED_AUTH_JWT_SECRET=...
```
https://va.linix.de/api/admin/request-headers?key=<ADMIN_API_KEY>
```
In der Ausgabe den Header finden, der den eingeloggten SSO-Usernamen trägt (z. B.
`X-Remote-User`, `Remote-User`, `Auth-User`, oder `Authorization: Basic …` mit dem
Usernamen). Diesen Namen in `TRUSTED_AUTH_HEADER` **und** in der nginx-`proxy_set_header
`-Zeile eintragen, Gateway + nginx neu laden. Danach `?key=` nicht mehr nutzen
(landet in Proxy-Logs) bzw. den Key rotieren.
In der nginx-Conf ist **keine** `proxy_set_header`-Identitätszeile nötig — Cookies
werden ohnehin durchgereicht.
> **Sicherheit:** Ohne `TRUSTED_AUTH_JWT_SECRET` wird die Cookie-Payload ungeprüft
> gelesen. Das ist nur sicher, weil (a) nur die Proxy-Quell-IP akzeptiert wird **und**
> (b) die Subdomain **per SSO geschützt** sein muss (dann lässt YunoHost nur validierte
> Cookies durch). Für Härtung das Portal-HS256-Secret in `TRUSTED_AUTH_JWT_SECRET`
> setzen → die Signatur wird dann selbst geprüft.
## 5. Test
- `https://va.linix.de/` lädt die UI, links „Angemeldet als <SSO-User>".