Manual

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:

  1. Turn on Client authentication (confidential) and Standard flow.
  2. Valid redirect URIs: http://typo3-v14.localhost:8088/*
  3. Create the client roles admin and editor and assign them to users or groups.
  4. Add a mapper under Client scopes → typo3-v14-dedicated → Add mapper → By configuration → User Client Role: client ID typo3-v14, token claim name Roles, 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 roleTYPO3
admingroup “Admin (Keycloak)” and admin flag on the user
editorgroup “Editor (Keycloak)”, permissions are maintained in the backend
  • typo3 oidc:setup-groups creates 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. sub is only stored for information in tx_oidc. Without the claim, matching falls back to sub as in the default.
  • Caution: a Keycloak user admin therefore also takes over the local setup admin admin, including groups and admin flag according to the Keycloak roles. Choose a different TYPO3_ADMIN_USERNAME if 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:

SettingValue
Front channel logoutOff
Backchannel logout URLhttp://host.docker.internal:8088/oidc/backchannel-logout
Backchannel logout session requiredOn

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.de uses a certificate from the Ostfalia RZ Root CA. The CA lives in config/certs/ and is added to the image.
  • Locally, /etc/hosts points id.dev.sonia.de to 127.0.0.1, where the Keycloak proxy listens on port 443. docker-compose.override.yml redirects the name to the Docker host inside the container. On a server with real DNS, leave the override file out.