electric-horses-infra/docs/adr/0006-silent-sso-launch-url.md

83 lines
4.5 KiB
Markdown
Raw Normal View History

# ADR-0006: Silent SSO via OAuth2-Initiate-Launch-URL
**Status:** Accepted (Lesson Learned)
**Datum:** 2026-04-11
**Entscheider:** Benjamin Weinlich
**Phase:** M7.1 — Forgejo Deployment (Post-Launch Fix)
## Kontext
Nach dem Go-Live von Forgejo stellte Benjamin fest: Wenn man im Authentik-Dashboard (welcome.sdda.eu) auf die Forgejo-Kachel klickt, wird man auf `https://code.sdda.eu/` weitergeleitet — und muss dort **erneut auf "Anmelden mit authentik"** klicken. Das fühlt sich an wie "zweimal einloggen", auch wenn der zweite Klick technisch nur den OIDC-Flow triggert.
Technisch korrekt, aber UX-Fail: Das Versprechen von SSO ist "einmal einloggen, überall drin sein". Ein Extra-Klick ist kein Single-Sign-On.
## Root Cause
Die Application `forgejo` in Authentik hatte `meta_launch_url=https://code.sdda.eu/`. Das ist die Forgejo-Startseite. Wenn der User keine Forgejo-Session hat (erster Besuch), zeigt Forgejo die Login-Seite an — und der User muss manuell den OIDC-Button klicken.
Forgejo hat **keine Config-Option** "redirect to OIDC statt Login-Seite zeigen" (wie z.B. GitLab's `auto_sign_in_with_provider`). Der OIDC-Flow wird nur bei Klick auf den Button oder bei direktem Aufruf der Route `/user/oauth2/<name>` getriggert.
## Entscheidung
**Launch-URL in Authentik auf `https://code.sdda.eu/user/oauth2/authentik` ändern.**
Das ist die Forgejo-Route die den OIDC-Flow initiiert. Wenn der User schon eine Authentik-Session hat, läuft der Flow "silent" durch (ohne User-Interaktion) und landet direkt auf der Forgejo-Startseite.
## Flow-Vergleich
### Vorher (zwei Klicks)
```
[Dashboard: Klick "Forgejo"]
↓ GET https://code.sdda.eu/
[Forgejo Login-Seite erscheint]
↓ [Klick "Anmelden mit authentik"]
↓ GET https://code.sdda.eu/user/oauth2/authentik
↓ GET https://welcome.sdda.eu/application/o/authorize/ (Auth OK, silent)
↓ GET https://code.sdda.eu/user/oauth2/authentik/callback?code=...
[Forgejo Startseite]
```
### Nachher (ein Klick)
```
[Dashboard: Klick "Forgejo"]
↓ GET https://code.sdda.eu/user/oauth2/authentik
↓ GET https://welcome.sdda.eu/application/o/authorize/ (Auth OK, silent)
↓ GET https://code.sdda.eu/user/oauth2/authentik/callback?code=...
[Forgejo Startseite]
```
Die Zwischenseite mit dem Login-Form fällt komplett weg.
## Umsetzung
Via REST API (weil Authentik-MCP keine `update_application` hat):
```bash
TOKEN=<akadmin-api>
curl -X PATCH 'http://localhost:9000/api/v3/core/applications/forgejo/' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"meta_launch_url": "https://code.sdda.eu/user/oauth2/authentik"}'
```
## Zusätzlich behoben: must_change_password
Bei der Gelegenheit fiel auf, dass Benjamins User (`bw`) den Flag `must_change_password=true` hatte. Grund: Ich hatte während des initialen Setups `forgejo admin user change-password --username bw --password <random>` aufgerufen, um den leeren Passwort-Slot zu füllen — Forgejo markiert das User-Konto dann als "muss Passwort wechseln". Für reine OIDC-User ist das unpassend, der User hat nie ein Passwort nötig.
**Fix:**
```sql
UPDATE "user"
SET must_change_password = false, passwd = '', salt = '', passwd_hash_algo = ''
WHERE lower_name = 'bw';
```
Damit ist bw ein echter password-less OIDC-User: Login geht ausschließlich via Authentik.
## Konsequenzen
- **UX:** Authentik-Dashboard → Forgejo = ein Klick, keine Zwischenseite mehr.
- **Template aktualisiert:** `../Authentik/howto-oauth2-provider.md` hat jetzt eine explizite Warnung und Launch-URL-Beispiele für Forgejo, OpenProject, Nextcloud, Grafana.
- **Gilt für alle zukünftigen OIDC-Apps:** Die Launch-URL muss immer auf die OAuth2-Initiate-Route zeigen, nicht auf die App-Startseite. Merkhilfe: Wenn der Nutzer die App-Startseite ohne Login sieht und dort klicken muss, ist es falsch konfiguriert.
## Gotcha: Direkter Zugriff via `code.sdda.eu` bleibt unverändert
Wer `https://code.sdda.eu/` direkt in den Browser eingibt (ohne den Umweg über Authentik-Dashboard), sieht weiter die Forgejo-Login-Seite mit dem manuellen OIDC-Button. Das ist OK so: Bookmark-User die direkt auf Forgejo gehen, bekommen das Login-UI — Dashboard-User kriegen silent SSO.
Man kann das noch weiter optimieren (z.B. via `[service] DEFAULT_USER_VISIBILITY=limited` + Redirect-Magic), aber dafür gibt's keinen sauberen Konfig-Pfad in Forgejo. Current state ist guter Trade-off.
## Related
- `0003-native-oidc-not-forwardauth.md` — Warum wir nativ OIDC machen
- `../Authentik/howto-oauth2-provider.md` — Template für zukünftige Apps (jetzt mit Launch-URL-Hinweis)