# 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/` 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= 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 ` 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)