---
title: Changelog
url: "https://b13.com/products/single-sign-on-for-typo3/changelog"
date: 2026-09-10
modified: 2026-11-10
---

# Changelog

Changelog Module “Single-Sign-On”
===================================

   Chapters of this Documentation        All notable changes to `b13/sso-authentication` are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

   2.0.3–2026–11–04
------------------

  ###  Fixed

- **A failed frontend SSO login no longer triggers a deprecation on TYPO3 v14.3.** The `sys_log` entry takes the visitor's IP address from the request instead of `GeneralUtility::getIndpEnv()`, which v14.3 deprecates.

  ###  Security

- **`onelogin/php-saml` is required from 4.3.1 on.** The constraint was `^4.0`, which let a project install anything from 4.0.0 up to 4.2.x. Those versions pull in a `robrichards/xmlseclibs` release affected by CVE-2025-66475, where a crafted assertion passes signature validation—an authentication bypass in the library this extension verifies assertions with. Which version a site runs is decided by the project, not by this package, so a project that had once resolved to a 4.0.x release kept it through every update of this extension. **Run `composer update onelogin/php-saml` after updating and check that the installed version is at least 4.3.1.**

   2.0.2 — 2026-10-19
--------------------

  ###  Fixed

- **A frontend SSO login only finds users in `userStoragePid`.** It searched every `fe_users` folder, so a person with accounts on two sites could be signed in to the other site's account. **If you run several sites with frontend SSO, clear `tx_sso_tenantid` and `tx_sso_objectidentifier` on records outside `userStoragePid` that received them since 2.0.0.**
- **Tenant plus object identifier wins over a username or email match.** Other matches are ordered by `uid`, so the same record wins on every login.

  ###  Documentation

- **The frontend and backend login flows are diagrams now.** "How It Works" drew both as ASCII art. Graphics now show the same steps, from the login page through the identity provider to the logged-in request, each with a full text description as alt text.

   2.0.1 — 2026-10-03
--------------------

  ###  Changed

- **`tx_sso_tenantid` and `tx_sso_objectidentifier` are no longer part of the claim mapping.** Both were always filled from the raw `tenantid` and `objectidentifier` claims anyway, so the forced mapping entries only duplicated that. A newly federated user now gets both columns set explicitly, and a `BeforeUserCreationEvent` listener sees them in `getUserData()` as before—the object identifier now with its name identifier fallback. The two Entra ID URIs are ordinary attribute names now and can be mapped to any other column. The matching `claimsMapping` entries are gone from the example configurations and the docs; existing configurations that still carry them keep working.
- **The `BackendBaseUrl` label says what the setting does.** It promised to prefix all URLs in the service provider metadata. In practice the assertion consumer service and single logout URLs are already absolute when it is applied, so the only value it can affect is a relative `entityId` — and it applies to the frontend as well, despite the name.

  ###  Fixed

- **A missing `noGroupsPage` no longer redirects a visitor to page 0.** A logged-in frontend user whose only groups are the two pseudo-groups was sent to whatever `noGroupsPage` said, including when the site did not set it — plus a PHP warning for the missing key, and a type error on a request without routing. Without the page configured there is now no redirect, and the visitor stays where they are.
- **A missing `loginStatusPage` falls back to the site's root page.** Same missing key, same warning, and a logout that ended on page 0. The fallback now matches what the assertion consumer service already did.
- **The single logout no longer leaves a used session index on the user.** After an identity-provider-initiated logout, `tx_sso_sessionindex` stayed on the record, so the next logout offered the identity provider an index for a session it had already closed.
- **A rejected assertion now reaches `sys_log`.** The entry *the response from the identity provider was rejected*—an invalid signature, an expired or replayed assertion, a `Destination` mismatch behind a reverse proxy—was never written, because TYPO3 drops a login request without a valid request token before it counts as a failed login. Only the *no TYPO3 user* entry made it into the Log module. Both are recorded now, as [Logging](https://b13.com/products/single-sign-on-for-typo3/documentation/logging) describes.

  ###  Security

- **The request token for the SSO return is only provided for a validated assertion.** It used to be enough that the submitted password equalled the internal SSO marker, so a forged login form could sign a visitor in to an account whose password had been set to that value.

  ###  Documentation

- **The documentation has images.** Seven of them, each next to the passage it illustrates: the SSO entry on the backend login screen, the extension settings, a frontend login template with the SSO link, the `tx_sso_*` columns on a backend user, a rejected login in the Log module, the Install Tool as the way back in, and the KeyCloak client side by side with the service provider metadata TYPO3 publishes. All of them were recorded against the bundled KeyCloak demo realm, so none shows data from a real identity provider.
- **Backend paths match TYPO3 v14.** The Log module is named with its v14 menu path, *Administration > Log*, next to v13's *System > Log*. The filter hint points at the *Channel* filter the module actually has, and the extension settings are referred to by the form's real name, *Extension Configuration*.

   2.0.0 — 2026-09-10
--------------------

  ###  Added

- **TYPO3 v14 support.** One code base now serves TYPO3 v13.4 LTS and v14.3. The backend login provider implements `modifyView()`, which both supported lines prefer over the removed `render()`, and the authentication service tolerates v14 dropping the `$passwordTransmissionStrategy` parameter from `processLoginData()`.
- **A listener can refuse to create a user.** `BeforeUserCreationEvent` now implements `StoppableEventInterface`, so a listener can call `preventCreation()` and the login is treated exactly like federation being switched off. Until now, every authenticated SAML identity received a TYPO3 account when `federation.enabled` was set, with no way to restrict that by claim — a real gap whenever the same identity provider also serves other applications, for example a company-wide Entra ID tenant where only one department should reach this TYPO3 instance.
- **Contact information in the generated service provider metadata is configurable.** Set `contactPerson` in the same configuration file as everything else; it is omitted entirely when unset. If you set a type (`technical`, `support`, `administrative`, `billing` or `other`), both `givenName` and `emailAddress` are required — otherwise the SAML toolkit rejects the whole configuration rather than just that block.

  ###  Changed

- **\[!!!\] Your own login template renders the frontend SSO button.** `ModifyFrontendLoginView` no longer merges a partial root path into the view. It assigns `additionalAuthenticationProviders`, `ssoAcsRedirectUrl` and `enforceSSO`, and rendering is up to the site's own `Login.html`. **A site that rendered the shipped `AzureAdLogin` partial by name gets a broken login page until its template is updated** — the new contract, including the `redirect_url` parameter, is documented in [Documentation/FrontendLogin.md](https://b13.com/products/single-sign-on-for-typo3/documentation/frontend-login).
- **The release archive contains only what an installation needs.** The test suite, the KeyCloak development fixtures, the DDEV environment, and the Playwright toolchain are excluded from the package. `Documentation/` is shipped deliberately, because that is what the marketplace reads.
- **\[!!!\] TYPO3 v12 is no longer supported.** This release requires TYPO3 `^13.4 || ^14.3` and PHP `^8.3`. Dropping v12 also collapsed the backend login provider onto a single implementation, because v13 and v14 both prefer `modifyView()` over `render()`.

  ###  Removed

- **\[!!!\] The `sso:migrateDatabaseNamespace` command.** It migrated column names from a pre-1.0 layout and has no purpose on a supported version.
- **\[!!!\] The shipped backend login layouts and the `SsoLogin` template.** They existed to style the provider switch per core version and are unnecessary now that one provider implementation covers both supported lines. Nothing in a normal installation references them; a site that copied or overrode them should remove those overrides.

  ###  Fixed

- **Existing users are matched reliably, so logins stop creating duplicates.** The lookup only matched on the TYPO3 username or a handful of raw claim names (`name`, `login_name`, `emailaddress`, `email`). Neither Entra ID's namespaced claim URIs nor a typical OID-based KeyCloak client ever sends those, so as soon as a user's TYPO3 username differed from what the identity provider sent, every login fell through to federation and created another account. The lookup now also uses the `claimsMapping`-resolved email, and tenant plus object identifier is a genuine alternative match instead of an additional condition that could only ever narrow an existing one.
- **The WS-Federation `name` claim no longer overwrites the SSO checkbox.** The default field mapping pointed the raw `name` claim — which ADFS and Entra ID commonly send — at `tx_sso_enabled`, a boolean field. The claim string landed in that column on every login and silently replaced whatever an editor had set there.
- **A listener can change the data of an existing user again.** `BeforeUserDataUpdatedEvent::setUpdateData()` had no effect at all: the update re-read the original user record after dispatching the event and wrote that instead. Removing a single field in a listener is now the way to keep SSO from overwriting a manually corrected value such as `realName`.
- **Finishing a password reset no longer bounces back to the identity provider.** When a stale `be_lastLoginProvider` cookie still pointed at SSO while the password form was rendered, the reset link and the form action were both built from that cookie. Submitting the password form also rewrote the cookie back to SSO on every login instead of correcting itself.

  ###  Security

- **The package no longer ships private keys.** Up to and including 1.3.4 the release archive carried a KeyCloak realm export with two RSA private keys in cleartext—the realm’s signing and encryption keys—alongside a certificate issued for an internal hostname, plus a service provider configuration file containing tenant identifiers, contact addresses, and a federation certificate. Neither `Resources/` nor `Configuration/` was excluded from the archive, so every 1.x installation received those files on disk. The keys are stripped, the example realm is neutralized, the KeyCloak fixtures are kept out of the package, and the tenant configuration file is deleted. **If you ever imported the shipped example realm into a KeyCloak you still operate, rotate that realm’s keys.**
- **A disabled backend user could get back in through SSO.** A disabled `be_users` row was invisible to the existing-user lookup, so federation created a second, active row with the same username and the rejected user logged in again instead of staying locked out. **If you run with `federation.enabled: true`, check `be_users` for duplicate usernames after updating.**

  ###  Documentation

- **`Documentation/` is now the source of truth** and the README covers only what you need in order to decide and to install. Start at [Documentation/Index.md](https://b13.com/products/single-sign-on-for-typo3/documentation).
- **The dead `sp:` block is gone from the backend example.** The example and two README snippets showed a nested `sp:` block with `entityId`, `assertionConsumerService` and `singleLogoutService`. Those values are assembled from the backend entry point plus the top-level `entityId` and `acsUrl` and were overwritten regardless of what the file said, so the block never had any effect. The example now shows the two top-level keys that are genuinely read.
- **`enabled` and `strict` no longer appear in the backend example.** `enabled` is never read for the backend service provider file — only the `enableBE` extension setting governs backend SSO, and the frontend's per-site `enabled` is a different key — so showing it implied a switch that never existed. `strict` is read, but by the SAML toolkit rather than by this extension, and it already matches the toolkit's default, so it is documented instead.
- **`allowEmailAsUsername` is documented.**

  ###  Tests

- **Add a functional test suite**, one test per branch of the existing-user lookup plus federation enabled and disabled, built on a mocked SAML response so the user details are constructed by production code.
- **Add unit tests for `SamlSettings`**, including a regression guard that nothing maps to `tx_sso_enabled` by default again.
- **Add an end-to-end suite that drives the real login flow.** Playwright walks a browser through frontend SSO, single logout, and the service provider metadata endpoint against a KeyCloak identity provider, with a demo site package and a committed DDEV environment providing the fixture site.
- **Static analysis runs against both supported TYPO3 lines.**

   1.3.4 — 2026-08-13
--------------------

  ###  Fixed

- **TYPO3 compatibility metadata in `ext_emconf.php`.** `constraints.depends.typo3` was `*` and now states `12.4.0-13.4.99`, matching the Composer requirement `^12.4 || ^13.4`. Composer installs were already constrained correctly; this fixes the compatibility information shown for non-Composer (TER) installs.

  ###  Changed

- **Package version moved to `extra.typo3/cms.version`.** The top-level `version` field was removed from `composer.json` to follow b13's release convention — `composer validate --strict` rejects a top-level `version`. No effect on installation.

   1.3.3 — 2026-08-13
--------------------

  ###  Documentation

- **Add this changelog** and link it from the README.

   1.3.2 — 2026-07-29
--------------------

  ###  Fixed

- **Unit test suite on TYPO3 v12.** The v12 job asserted an `X-Forwarded-Proto` behaviour that only TYPO3 v13 provides — v12 does not evaluate that header, so the expectation is now skipped on v12, letting the pipeline pass on both core lines.

   1.3.1 — 2026-07-29
--------------------

  ###  Fixed

- **SSO behind a TLS-terminating reverse proxy.** The SAML toolkit now follows TYPO3's own view of the current URL instead of reconstructing it from `$_SERVER`. Previously the `Destination` in the assertion did not match the internal `http` URL the proxy forwarded, so logins failed silently and fell back to the login form. The usual `reverseProxyIP` / `reverseProxySSL` configuration is now all that is required (on TYPO3 v12 `reverseProxySSL` is mandatory). See [Documentation/ReverseProxy.md](https://b13.com/products/single-sign-on-for-typo3/documentation/running-behind-a-reverse-proxy).

   1.3.0 — 2026-07-28
--------------------

  ###  Added

- **Logging for failed SSO logins.** A rejected login now records *why* it failed: rejected assertions are written to `sys_log` (visible in **System > Log**, distinguishing a rejected IdP response from a missing TYPO3 user), and full technical detail goes to the PSR-3 logger under the `B13.SSOAuthentication` component. See [Documentation/Logging.md](https://b13.com/products/single-sign-on-for-typo3/documentation/logging) for the log levels and a file-writer example.

   1.2.0 — 2026-07-28
--------------------

  ###  Added

- **`enforceSSO` option for dual or SSO-only login.** Off by default, so SSO and username/password are offered side by side. When enabled it makes SSO the only accepted login (password logins are rejected during authentication, not just hidden). Configured per scope: a top-level key in the backend YAML config file, and per site under `settings.sso_authentication` for the frontend.

  ###  Fixed

- **Resolve the backend entry point** instead of hard-coding `/typo3/`, so a custom backend path or a subdirectory installation derives the correct SAML endpoints on both v12 and v13.
- **Backend-specific default for the ACS endpoint**, which follows a custom backend entry point automatically.
- **Ship the backend login layout per core version** (`v12` / `v13`).
- **Accept a group id in `valueMapping`** without requiring it to be wrapped in an array.
- Make the unit test pipeline actually run the tests.

   1.1.0 — 2026-05-07
--------------------

  ###  Added

- **`BeforeUserDataUpdatedEvent`** — a PSR-14 event fired when an existing user is updated from a SAML response, alongside the existing user-creation event.
- CI pipeline and the initial unit-test infrastructure.
- Backend login template updated for TYPO3 v13.

  ###  Fixed

- **Weak open-redirect protection in `sanitizeRelayState`.** (security)
- Malformed query strings in SSO redirect URLs.
- `ModifyBackendLoginView` no longer uses frontend settings.

   1.0.x and earlier
-------------------

The 1.0 line established the extension: SAML authentication for the TYPO3 backend and frontend, user federation with claims mapping, and Single Logout. Later 1.0.x releases lowered the requirement to PHP 8.2, removed PHP 8.3-only syntax, fixed a range of claims-handling issues (including using the email as nameId), added exception logging, and cleaned up PHP warnings. See the tags `1.0.0`–`1.0.5` for details.