electric-horses-infra/docs/adr/0006-silent-sso-launch-url.md
Benjamin Weinlich 88c541c9ed docs(adr): mirror 6 ADRs from M7.1 into repo
Adds the Architecture Decision Records that were written during the
Forgejo deployment (M7.1) as part of moving docs from the iCloud folder
into this versioned repository.

Includes:
- ADR-0001: Forgejo vs Gitea (non-profit stewardship)
- ADR-0002: ai-apps placement (no separate VM)
- ADR-0003: Native OIDC, not ForwardAuth
- ADR-0004: Subdomain code.sdda.eu
- ADR-0005: Volume mount on /data (lesson learned)
- ADR-0006: Silent SSO via OAuth2 launch URL (lesson learned)

Plus a docs/adr/README.md that explains the ADR format, lists the
current ADRs, and provides a template for future entries.

Refs OP#1118
2026-04-11 22:26:05 +02:00

4.5 KiB

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):

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:

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.

  • 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)