Handbuch

Anmeldung über Keycloak

Backend-Login per OpenID Connect: Keycloak-Client, Rollen, Login-Seite, Single Logout und Back-Channel-Logout.

Überblick

Die Appliance verwendet causal/oidc 6.x, nur für das Backend. Die Anmeldung ist aktiv, sobald TYPO3_OIDC_CLIENT_ID in der .env gesetzt ist. Die Endpunkte werden aus TYPO3_OIDC_ISSUER abgeleitet. Der normale Passwort-Login bleibt daneben erhalten, zum Beispiel für den Setup-Admin.

Die eigene Extension oidc_backend ergänzt, was causal/oidc fehlt: Zuordnung über den Benutzernamen, Admin-Flag aus Rollen, OIDC als Standard-Login und Abmeldung in beide Richtungen.

Keycloak-Client in Kürze

Client typo3-v14 im Realm sonia, Schritt für Schritt mit Screenshots auf der Seite Keycloak-Client einrichten:

  1. Client authentication an (confidential), Standard flow an.
  2. Valid redirect URIs: http://typo3-v14.localhost:8088/*
  3. Client-Rollen admin und editor anlegen und Benutzern oder Gruppen zuweisen.
  4. Mapper unter Client scopes → typo3-v14-dedicated → Add mapper → By configuration → User Client Role: Client ID typo3-v14, Token Claim Name Roles, Multivalued an, Add to userinfo an.

EXT:oidc liest ausschließlich den Claim Roles (großes R) aus der Userinfo-Antwort. oidc_backend übernimmt ersatzweise auch roles oder resource_access.typo3-v14.roles. Der Mapper ist trotzdem nötig, damit Keycloak die Rollen überhaupt im Userinfo ausliefert.

Rollen und Backend-Gruppen

Keycloak-RolleTYPO3
adminGruppe „Admin (Keycloak)“ und Admin-Flag am Benutzer
editorGruppe „Editor (Keycloak)“, Rechte werden im Backend gepflegt
  • Die Gruppen legt typo3 oidc:setup-groups beim Containerstart an. Der Befehl ist idempotent.
  • Die Zuordnung läuft über das Feld „Case-insensitive pattern to match OpenID Connect role names“ der Backend-Gruppe (| = oder, * = Platzhalter). Weitere Gruppen legt man im Backend mit eigenem Muster an.
  • Bei jedem Login werden alle Gruppen mit Muster neu gesetzt. Manuell vergebene Gruppen ohne Muster bleiben erhalten. Auch das Admin-Flag wird bei jedem Login gesetzt oder entzogen.
  • Benutzer ohne passende Rolle werden nicht angelegt.
  • Zuordnung über preferred_username, nicht über die interne Keycloak-ID, denn die ändert sich bei LDAP-Neuimporten. Ein Keycloak-Login übernimmt einen vorhandenen, nicht gelöschten Backend-Benutzer mit gleichem Namen, sonst wird er neu angelegt. sub steht nur informativ in tx_oidc. Fehlt der Claim, wird wie im Standard über sub zugeordnet.
  • Achtung: Ein Keycloak-Benutzer admin übernimmt damit auch den lokalen Setup-Admin admin, samt Gruppen und Admin-Flag laut Keycloak-Rollen. Gegebenenfalls TYPO3_ADMIN_USERNAME anders wählen.

Login-Seite

Bei aktivem OIDC ist der OIDC-Login der Standard auf /typo3/login. Das gilt auch, wenn TYPO3 sich per Cookie be_lastLoginProvider einen früheren Passwort-Login gemerkt hat. oidc_backend blendet außerdem den Umschalter „Login with username and password“ aus.

Der Passwort-Login bleibt als Notzugang direkt erreichbar, zum Beispiel wenn Keycloak nicht erreichbar ist:

http://typo3-v14.localhost:8088/typo3/login?loginProvider=1433416747

Logout (Single Logout)

EXT:oidc meldet beim Logout nicht bei Keycloak ab. Die SSO-Session bliebe bestehen, und der nächste Klick auf „Login“ würde ohne Passwortabfrage wieder anmelden. oidc_backend ergänzt daher einen RP-Initiated Logout: Beim OIDC-Login wird das ID-Token in der Backend-Session gemerkt. Beim Backend-Logout leitet TYPO3 auf den Keycloak-Logout-Endpunkt (id_token_hint) und von dort zurück zur Login-Seite. Lokale Passwort-Logins sind davon nicht betroffen.

Keycloak muss http://typo3-v14.localhost:8088/typo3/login als Valid post logout redirect URI akzeptieren. Der Standardwert + übernimmt die Valid redirect URIs.

Back-Channel-Logout

Umgekehrt beendet ein Logout in Keycloak auch die TYPO3-Backend-Session, etwa ein Logout in einer anderen Anwendung, im Account-Portal oder durch einen Admin. Keycloak schickt dazu ein signiertes logout_token per POST /oidc/backchannel-logout. oidc_backend prüft Signatur (JWKS des Realms), iss, aud, iat/exp, events und das Fehlen von nonce. Danach löscht es die Backend-Sessions mit derselben Keycloak-Session-ID (sid), die beim Login in der Session gespeichert wurde.

Zugeordnet wird ausschließlich über die sid, nie über sub. Im Logout-Token steht immer die interne Keycloak-ID, denn Protokoll-Mapper wirken dort nicht. Diese ID ändert sich bei LDAP-Benutzern mit jedem Neuimport. Im Realm sonia ist sub in ID-Token und Userinfo deshalb per Mapper auf den stabilen Benutzernamen (eid…) gelegt. Logout-Tokens ohne sid werden mit 400 abgelehnt. Das Ergebnis steht in var/log/typo3_oidc_*.log.

Keycloak-Client typo3-v14 → Einstellungen → Logout settings:

EinstellungWert
Front channel logoutAus
Backchannel logout URLhttp://host.docker.internal:8088/oidc/backchannel-logout
Backchannel logout session requiredAn

Keycloak läuft lokal im Docker-Netz lr7 und erreicht TYPO3 über host.docker.internal:8088. Dieser Hostname ist deshalb in TYPO3_TRUSTED_HOSTS_PATTERN erlaubt. Auf einem Server trägt man die öffentliche TYPO3-URL ein und entfernt den Eintrag aus dem Muster. Voraussetzung ist, dass die Sessions in der Datenbank liegen (be_sessions, TYPO3-Standard).

Cookies

Bei aktivem OIDC wird BE.cookieSameSite auf lax gesetzt. Mit dem TYPO3-Standard strict schickt der Browser das Backend-Cookie in der Weiterleitungskette von Keycloak zurück nicht mit. Man landet dann nach erfolgreichem Login wieder auf der Login-Seite.

Debug-Logging

TYPO3_OIDC_DEBUG=1 in der .env schreibt den Ablauf nach var/log/typo3_oidc_*.log. Achtung: Das Log enthält vollständige Access- und ID-Tokens. Nur zur Fehlersuche einschalten und das Log danach löschen.

Zertifikate und lokale Namensauflösung

  • id.dev.sonia.de nutzt ein Zertifikat der Ostfalia RZ Root CA. Die CA liegt in config/certs/ und wird ins Image übernommen.
  • Lokal zeigt id.dev.sonia.de per /etc/hosts auf 127.0.0.1, wo der Keycloak-Proxy auf Port 443 lauscht. docker-compose.override.yml leitet den Namen im Container auf den Docker-Host um. Auf einem Server mit echtem DNS lässt man die Override-Datei weg.