Sign-in via Keycloak
Backend login via OpenID Connect: Keycloak client, roles, login page, single logout and back-channel logout.
Overview
The appliance uses causal/oidc 6.x, for the backend only. Sign-in is active as soon as TYPO3_OIDC_CLIENT_ID is set in .env. The endpoints are derived from TYPO3_OIDC_ISSUER. The normal password login remains available, for example for the setup admin.
The custom extension oidc_backend adds what causal/oidc lacks: matching by user name, the admin flag from roles, OIDC as the default login and logout in both directions.
Keycloak client in brief
Client typo3-v14 in realm sonia, step by step with screenshots on the page Setting up the Keycloak client:
- Turn on Client authentication (confidential) and Standard flow.
- Valid redirect URIs:
http://typo3-v14.localhost:8088/* - Create the client roles
adminandeditorand assign them to users or groups. - Add a mapper under Client scopes → typo3-v14-dedicated → Add mapper → By configuration → User Client Role: client ID
typo3-v14, token claim nameRoles, Multivalued on, Add to userinfo on.
EXT:oidc only reads the claim Roles (capital R) from the userinfo response. As a fallback, oidc_backend also accepts roles or resource_access.typo3-v14.roles. The mapper is still required, otherwise Keycloak does not include the roles in the userinfo response at all.
Roles and backend groups
| Keycloak role | TYPO3 |
|---|---|
admin | group “Admin (Keycloak)” and admin flag on the user |
editor | group “Editor (Keycloak)”, permissions are maintained in the backend |
typo3 oidc:setup-groupscreates the groups when the container starts. The command is idempotent.- Matching uses the backend group field “Case-insensitive pattern to match OpenID Connect role names” (
|= or,*= wildcard). Create further groups in the backend with their own pattern. - Every login resets all groups that have a pattern. Groups without a pattern that were assigned manually are kept. The admin flag is also set or removed on every login.
- Users without a matching role are not created.
- Matching by
preferred_username, not by the internal Keycloak ID, because that changes with every LDAP re-import. A Keycloak login takes over an existing, non-deleted backend user with the same name, otherwise a new user is created.subis only stored for information intx_oidc. Without the claim, matching falls back tosubas in the default. - Caution: a Keycloak user
admintherefore also takes over the local setup adminadmin, including groups and admin flag according to the Keycloak roles. Choose a differentTYPO3_ADMIN_USERNAMEif needed.
Login page
With OIDC active, the OIDC login is the default on /typo3/login. This also applies when TYPO3 has remembered an earlier password login in the be_lastLoginProvider cookie. oidc_backend also hides the “Login with username and password” switch.
The password login remains directly reachable as an emergency access, for example when Keycloak is unavailable:
http://typo3-v14.localhost:8088/typo3/login?loginProvider=1433416747
Logout (single logout)
EXT:oidc does not log out of Keycloak. The SSO session would remain, and the next click on “Login” would sign you in again without asking for a password. oidc_backend therefore adds an RP-initiated logout: the OIDC login stores the ID token in the backend session. On backend logout, TYPO3 redirects to the Keycloak logout endpoint (id_token_hint) and from there back to the login page. Local password logins are not affected.
Keycloak must accept http://typo3-v14.localhost:8088/typo3/login as a Valid post logout redirect URI. The default value + reuses the Valid redirect URIs.
Back-channel logout
Conversely, a logout in Keycloak also ends the TYPO3 backend session, for example a logout in another application, in the account portal or by an administrator. Keycloak sends a signed logout_token via POST /oidc/backchannel-logout. oidc_backend checks the signature (the realm’s JWKS), iss, aud, iat/exp, events and the absence of nonce. It then deletes the backend sessions with the same Keycloak session ID (sid), which was stored in the session at login.
Matching uses only the sid, never sub. The logout token always carries the internal Keycloak ID, because protocol mappers do not apply there. For LDAP users, this ID changes with every re-import. In realm sonia, a mapper therefore sets sub in the ID token and userinfo to the stable user name (eid…). Logout tokens without sid are rejected with 400. The result is logged to var/log/typo3_oidc_*.log.
Keycloak client typo3-v14 → Settings → Logout settings:
| Setting | Value |
|---|---|
| Front channel logout | Off |
| Backchannel logout URL | http://host.docker.internal:8088/oidc/backchannel-logout |
| Backchannel logout session required | On |
Locally, Keycloak runs in the Docker network lr7 and reaches TYPO3 via host.docker.internal:8088. That host name is therefore allowed in TYPO3_TRUSTED_HOSTS_PATTERN. On a server, enter the public TYPO3 URL and remove the entry from the pattern. Sessions must be stored in the database (be_sessions, the TYPO3 default).
Cookies
With OIDC active, BE.cookieSameSite is set to lax. With the TYPO3 default strict, the browser does not send the backend cookie along the redirect chain coming back from Keycloak. You would end up on the login page again after a successful login.
Debug logging
TYPO3_OIDC_DEBUG=1 in .env writes the flow to var/log/typo3_oidc_*.log. Caution: the log contains complete access and ID tokens. Only enable it for troubleshooting and delete the log afterwards.
Certificates and local name resolution
id.dev.sonia.deuses a certificate from the Ostfalia RZ Root CA. The CA lives inconfig/certs/and is added to the image.- Locally,
/etc/hostspointsid.dev.sonia.deto 127.0.0.1, where the Keycloak proxy listens on port 443.docker-compose.override.ymlredirects the name to the Docker host inside the container. On a server with real DNS, leave the override file out.