---
title: "Changelog"
manual: "Passkeys Frontend Authentication"
version: "1.0"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-passkeys-fe:changelog@1.0"
source: "Changelog/Index.rst"
rendered: "2026-09-21T10:38:06+00:00"
---

# Changelog {#changelog}

## Version 1.0.1 {#version-1-0-1}

*Login fixes, and the end-to-end suite in CI*

### Security {#security}

-   **The login options endpoint no longer tells a caller which usernames
    exist.** A username-first request for a known account was answered with
    assertion options and status 200, one for an unknown account with 401 and
    an error body, so the frontend users of a site could be enumerated one
    request at a time. Unknown accounts and accounts without a passkey on the
    site are now answered with decoy options: same status, same keys, and
    credential descriptors derived from the username with HMAC-SHA256 under
    the encryption key, so they are stable per username and cannot be told
    apart from real ones. The ceremony then fails in the browser the way a
    cancelled one does.
-   **All username-first answers take the same time.** The random delay that
    used to sit in the unknown-account branch ran on that side only, which made
    the response time a second way to tell the answers apart. Every
    username-first answer now leaves after a shared floor of 150 ms. Work that
    runs past that floor still shows its own duration; such a request logs a
    warning with the overrun.

### Bugfixes {#bugfixes}

-   **A passkey login on a page without felogin now establishes a session.**
    After a successful ceremony the script posted the login token through a
    form it assembled itself, and TYPO3 refuses a frontend login whose
    `__RequestToken` is missing or carries the wrong scope — silently, with
    a 200 and no session cookie. The login plugin template now renders a
    hidden form whose token has the scope `core/user-auth/fe`, and the script
    only submits forms TYPO3 rendered.
-   **The backend module renders on TYPO3 13.** The dashboard and help
    templates passed the `state` of `f:be.infobox` as a string; TYPO3 13
    types that argument `int` and answered every module page with 503.

### Tests {#tests}

-   The end-to-end suite runs. 15 Playwright tests drive registration,
    discoverable login through to an authenticated session, credential
    management, enrollment, recovery and the backend module against a TYPO3
    instance the shared test runner provisions, and
    `.github/workflows/e2e.yml` runs them on TYPO3 13 and 14 for every pull
    request. Before this release every specification was skipped and no
    workflow ran them.

## Version 1.0.0 {#version-1-0-0}

*Stable, and paired with nr_passkeys_be 1.0*

### Breaking / Important {#breaking-important}

-   **The extension state changes from \`\`beta\`\` to \`\`stable\`\`.** From this
    release on the public API follows semantic versioning: a removal or an
    incompatible change to a public class, method or configuration setting
    needs a new major version.
-   **\`\`nr_passkeys_be\`\` 1.0.0 or newer is required.** That release removed
    `RateLimiterService::checkRateLimit()` and `::recordAttempt()`, which
    this extension called in `LoginController` and `RecoveryController`.
    Both call sites now use `consumeRateLimit()`, which performs the check
    and the increment inside one critical section — the separate check-then-
    record pair left a window in which concurrent requests could all pass the
    check before any of them incremented. No installation could reach the
    broken combination: the dependency constraint refused `nr_passkeys_be`
    1.0.0 until this release.

### Bugfixes {#bugfixes-1}

-   **Passkey login works on SQLite-backed installations.**
    `tx_nrpasskeysfe_credential.credential_id` is a `varbinary` column, but
    the lookups bound it as a plain string and `save()` declared no column
    types. MySQL compares that regardless; SQLite stores a string-bound
    parameter as a TEXT storage class, which never equals the BLOB the value
    was written as, so the credential could not be found and the login failed.
    The lookups now bind with `ParameterType::BINARY` and the insert declares
    `credential_id`, `user_handle` and `public_key_cose` by type.

### Tests {#tests-1}

-   The functional suite passes on SQLite as well as MySQL: 113 tests on both,
    where SQLite previously produced twelve failures. The end-to-end
    specifications under `Tests/E2E/` remain drafts and are not part of any
    suite that runs.

## Version 0.6.0 {#version-0-6-0}

*Conditional UI and CType plugin registration*

This release shipped without a changelog entry. Its contents:

### Features {#features}

-   **WebAuthn Conditional UI on the login plugin** -- the browser offers a
    stored passkey directly in the username field's autofill menu, so a
    returning user never has to press the passkey button. The plugin's
    discoverable switch governs it.
-   **Plugins register as CType on both supported TYPO3 versions**, so the
    content elements appear in the element wizard on v13 and v14 alike.
-   **Rector runs with the shared organisation configuration**, including the
    TYPO3 v13 level set.

## Version 0.5.0 {#version-0-5-0}

*Unified passkey dashboard widgets*

### Breaking / Important {#breaking-important-1}

-   **Standalone dashboard widgets removed** -- `nr_passkeys_fe` no
    longer registers its own `Passkey adoption` and
    `Active passkey credentials` dashboard widgets. When both
    extensions are installed the dashboard previously showed four
    near-identical widgets; it now shows the single unified widget set
    owned by `nr_passkeys_be`.
-   **Frontend adoption is now a segment of the unified widgets** --
    Frontend statistics appear as the "Frontend users" segment (a second
    doughnut ring and a summed credential count) of the
    `nr_passkeys_be` widgets, contributed via the new
    `nr_passkeys_be.adoption_stats_provider` service tag
    (`FrontendPasskeyAdoptionStatsProvider`). Backend and frontend user
    populations are shown separately, never summed.
-   **Requires** `netresearch/nr-passkeys-be` **^0.12** -- the
    extension point (`PasskeyAdoptionStatsProviderInterface` and the
    `PasskeyAudienceStats` DTO) is provided from `nr_passkeys_be`
    0.12.0. The Composer constraint and the `ext_emconf.php` dependency
    were tightened accordingly.
-   **TYPO3 v13 compatibility shim removed** -- `nr_passkeys_fe` no
    longer references any `typo3/cms-dashboard` symbol, so the
    `AdminOnlyWidgetInterface` compat shim (and its `autoload.files`
    entry) has been dropped.

## Version 0.1.0 {#version-0-1-0}

*Initial release*

This is the first public release of Passkeys Frontend Authentication
(`nr_passkeys_fe`). It provides passkey-first login for TYPO3
frontend users with all core features.

### Features {#features-1}

-   **Passkey-first login** -- Discoverable (usernameless) and
    username-first login flows via the NrPasskeysFe:Login plugin.
    Supports all FIDO2/WebAuthn-compliant authenticators.
-   **felogin integration** -- Injects a passkey button into the
    standard felogin plugin via PSR-14 event listener. No login provider
    switching required.
-   **Self-service management** -- Frontend users can enroll, rename,
    and revoke their own passkeys via the NrPasskeysFe:Management plugin.
-   **Recovery codes** -- Users can generate 10 one-time recovery codes
    (bcrypt hashed) as a fallback when no authenticator device is
    available.
-   **Per-site RP ID** -- Each TYPO3 site has an independent WebAuthn
    Relying Party configuration via `config.yaml`.
-   **Per-group enforcement** -- Four enforcement levels (Off, Encourage,
    Required, Enforced) configurable per site and per frontend user
    group with configurable grace periods.
-   **Post-login interstitial** -- Users without a passkey are shown an
    enrollment interstitial when enforcement level is Required or
    Enforced.
-   **Backend admin module** -- Administrators can view adoption
    statistics, manage credentials, and configure enforcement from
    **Admin Tools > Passkey Management FE**.
-   **PSR-14 events** -- Seven events for extensibility: before/after
    authentication, before/after enrollment, enforcement level resolved,
    passkey removed, recovery codes generated.
-   **Security hardened** -- HMAC-signed challenges, nonce replay
    protection, per-IP rate limiting, and account lockout (shared with
    `nr-passkeys-be`).
-   **Vanilla JavaScript** -- Zero runtime npm dependencies. The
    frontend JavaScript uses only the native WebAuthn browser API.

### Requirements {#requirements}

-   TYPO3 13.4 LTS or 14.1+
-   PHP 8.2+
-   `netresearch/nr-passkeys-be` ^0.6
-   HTTPS

### Known limitations {#known-limitations}

-   Magic link login is deferred to v0.2 (ADR-011). The event class
    and service will be added in v0.2.
-   No admin-initiated passkey registration on behalf of users.
