#13146·authelia

Support setting the unsolicited output setting to allow invalid client outputs that are not permitted in the spec

Author: max403Created Sep 13, 2026Updated Sep 14, 2026
Labelspriority/4/normaltype/featurestatus/needs-designtype/bug/third-party

Version

v4.39.24, v4.39.26

Deployment Method

Docker

Reverse Proxy

Traefik

Reverse Proxy Version

No response

Description

Passkey authentication via WebAuthn fails on Safari (macOS and iOS) with the following error:

Error occurred validating a WebAuthn passkey authentication challenge:
error performing the login validation
error="Error validating the client extension outputs: Client returned the \"appid\" extension output which was not requested (invalid_request)"

The same YubiKey works perfectly on Firefox (Linux, macOS) and Chrome. The problem is specific to WebKit-based browsers (Safari on macOS and iOS, and all browsers on iOS since they are forced to use WebKit).

Root cause

WebKit (Safari) always returns the appId extension output in clientExtensionResults, even when the appid extension was not requested by the Relying Party. The value returned is false when the extension was not used, but the field is still present:

json
clientExtensionResults: { appId: false }

Authelia's WebAuthn validation layer strictly rejects any extension output that was not explicitly requested by the server, which causes the authentication to fail before the signature is even verified.

This behavior is documented in the WebAuthn specification discussions: clients may return unsolicited extension outputs, and Relying Parties SHOULD be prepared to handle this situation, either by ignoring the unsolicited output or by rejecting the assertion based on local policy.

The go-webauthn library used by Authelia already exposes an option to control this behavior:

go
ExtensionsUnsolicitedOutputPolicy: protocol.UnsolicitedOutputPolicyIgnore

Reproduction

  1. Configure Authelia v4.39.x with:
    • webauthn.enable_passkey_login: true
    • webauthn.experimental_enable_passkey_uv_two_factors: true
    • access_control.default_policy: two_factor
  2. Register a YubiKey as a Passkey from a non-WebKit browser (or directly from Safari — the registration works).
  3. Attempt to log in from Safari on macOS or any browser on iOS.
  4. Touch the YubiKey, enter the PIN, touch again.
  5. Authentication fails with the appId extension error.

Expectations

The login should succeed. The unsolicited appId: false output should be ignored, since Authelia never requested the appid extension.

Configuration (Authelia)

yaml
webauthn:
  display_name: "Authelia"
  enable_passkey_login: true
  attestation_conveyance_preference: 'indirect'
  selection_criteria:
    attachment: 'cross-platform'
    user_verification: 'preferred'
  metadata:
    enabled: true
    cache_policy: 'relaxed'

Build Information

bash
Last Tag: v4.39.26
State: tagged clean
Branch: v4.39.26
Commit: f6fb0a300877e8c3378dc472c02383c75294d84e
Build Number: 58782
Build OS: linux
Build Arch: amd64
Build Compiler: gc
Build Date: Sat, 12 Sep 2026 23:55:42 +1000
Development: false
Extra: 

Go:
    Version: go1.27.1
    Module Path: github.com/authelia/authelia/v4
    Executable Path: github.com/authelia/authelia/v4/cmd/authelia

Logs (Authelia)

bash
authelia  | time="2026-09-13T23:54:12+02:00" level=debug msg="Loaded Configuration Sources" files="[/config/configuration.yml]" filters="[]"
authelia  | time="2026-09-13T23:54:12+02:00" level=debug msg="Logging Initialized" fields.level=debug file= format= keep_stdout=false
authelia  | time="2026-09-13T23:54:12+02:00" level=debug msg="Process user information" gid=0 name=root uid=0 username=root
authelia  | time="2026-09-13T23:54:12+02:00" level=info msg="Authelia v4.39.26 is starting"
authelia  | time="2026-09-13T23:54:12+02:00" level=info msg="Log severity set to debug"
authelia  | time="2026-09-13T23:54:12+02:00" level=debug msg="Registering OpenID Connect 1.0 client with client id 'immich' and policy 'two_factor'"
authelia  | time="2026-09-13T23:54:12+02:00" level=info msg="Storage schema is being checked for updates"
authelia  | time="2026-09-13T23:54:12+02:00" level=info msg="Storage schema is already up to date"
authelia  | time="2026-09-13T23:54:13+02:00" level=info msg="Startup complete"
authelia  | time="2026-09-13T23:54:13+02:00" level=info msg="Listening for non-TLS connections on '[::]:9091' path '/'" server=main service=server
authelia  | time="2026-09-13T23:54:35+02:00" level=error msg="Error occurred validating a WebAuthn passkey authentication challenge: error performing the login validation" error="Error validating the client extension outputs: Client returned the \"appid\" extension output which was not requested (invalid_request)" method=POST path=/api/firstfactor/passkey remote_ip=192.168.10.114 stack="github.com/authelia/authelia/v4/internal/regulation/types.go:48        NewBan\ngithub.com/authelia/authelia/v4/internal/middlewares/bridge.go:70      (*BridgeBuilder).Build.func1.1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:70     SecurityHeadersCSPNone.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:110    SecurityHeadersNoStore.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:34     SecurityHeadersBase.func1\ngithub.com/fasthttp/[email protected]/router.go:441                        (*Router).Handler\ngithub.com/authelia/authelia/v4/internal/middlewares/log_request.go:18 LogRequest.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/errors.go:42      RecoverPanic.func1\ngithub.com/valyala/[email protected]/server.go:2641                     (*Server).serveConnCounted\ngithub.com/valyala/[email protected]/server.go:2329                     (*Server).serveConn-fm\ngithub.com/valyala/[email protected]/workerpool.go:225                  (*workerPool).workerFunc\ngithub.com/valyala/[email protected]/workerpool.go:197                  (*workerPool).getCh.func1\nruntime/asm_amd64.s:1264                                               goexit"
authelia  | time="2026-09-13T23:54:35+02:00" level=debug msg="Mark Passkey authentication attempt made by user ''" method=POST path=/api/firstfactor/passkey remote_ip=192.168.10.114
authelia  | time="2026-09-13T23:54:35+02:00" level=error msg="Unsuccessful Passkey authentication attempt by user ''" method=POST path=/api/firstfactor/passkey remote_ip=192.168.10.114 stack="github.com/authelia/authelia/v4/internal/handlers/response.go:503                    doMarkAuthenticationAttemptWithRequest\ngithub.com/authelia/authelia/v4/internal/handlers/response.go:486                    doMarkAuthenticationAttempt\ngithub.com/authelia/authelia/v4/internal/handlers/handler_firstfactor_passkey.go:200 FirstFactorPasskeyPOST\ngithub.com/authelia/authelia/v4/internal/middlewares/bridge.go:70                    (*BridgeBuilder).Build.func1.1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:70                   SecurityHeadersCSPNone.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:110                  SecurityHeadersNoStore.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/headers.go:34                   SecurityHeadersBase.func1\ngithub.com/fasthttp/[email protected]/router.go:441                                      (*Router).Handler\ngithub.com/authelia/authelia/v4/internal/middlewares/log_request.go:18               LogRequest.func1\ngithub.com/authelia/authelia/v4/internal/middlewares/errors.go:42                    RecoverPanic.func1\ngithub.com/valyala/[email protected]/server.go:2641                                   (*Server).serveConnCounted\ngithub.com/valyala/[email protected]/server.go:2329                                   (*Server).serveConn-fm\ngithub.com/valyala/[email protected]/workerpool.go:225                                (*workerPool).workerFunc\ngithub.com/valyala/[email protected]/workerpool.go:197                                (*workerPool).getCh.func1\nruntime/asm_amd64.s:1264

Logs (Proxy / Application)

bash

Documentation

Actual behavior

Authelia rejects the assertion with:

Client returned the "appid" extension output which was not requested (invalid_request)

Proposed fix

In internal/middlewares/authelia_context.go, in the GetWebAuthnProvider() function, add the following field to the webauthn.Config struct:

go
config := &webauthn.Config{
    RPID:                  origin.Hostname(),
    RPDisplayName:         ctx.Configuration.WebAuthn.DisplayName,
    RPOrigins:             []string{origin.String()},
    AttestationPreference: ctx.Configuration.WebAuthn.ConveyancePreference,
    ExtensionsUnsolicitedOutputPolicy: protocol.UnsolicitedOutputPolicyIgnore, // <-- add this
    // ... rest of the config
}

This tells go-webauthn to ignore any extension output that was not explicitly requested by the server. This is consistent with the WebAuthn specification's recommendation for Relying Parties to tolerate unsolicited extension outputs.

I have verified that applying this patch locally (building Authelia from source with this one-line change) fully resolves the issue on Safari macOS and iOS, while Chrome and Firefox continue to work as before.

Environment

  • Authelia version: v4.39.26 (also reproduced on v4.39.24)
  • Installation: Docker (official authelia/authelia image, replaced binary with a patched build)
  • Reverse proxy: Traefik v3
  • YubiKey model: YubiKey 5 (FIDO2, with PIN and user verification)
  • Browsers affected:
    • Safari 26.x on macOS 26 (Tahoe) — ❌ fails
    • Safari on iOS 26 — ❌ fails
    • Any browser on iOS (forced WebKit) — ❌ fails
  • Browsers working correctly:
    • Firefox on Linux — ✅
    • Firefox on macOS — ✅
    • Chrome on macOS — ✅

Additional context

  • The appid extension is a FIDO U2F backwards-compatibility extension. It is not needed for pure FIDO2/WebAuthn Passkeys.
  • The YubiKey in question has no U2F credentials registered; the appId field is emitted unconditionally by WebKit regardless of the authenticator's capabilities.
  • Setting attestation_conveyance_preference to indirect or none does not change the behavior — WebKit still returns appId: false.
  • This is not a configuration issue: the same config works on Firefox and Chrome on the same machine, pointing to a WebKit-specific behavior.

Relevant W3C WebAuthn specification discussion

This behavior is explicitly covered by the WebAuthn specification. A merged W3C pull request (PR #1289, "Initial proposal to fix #1287") relaxed the previous strict requirement for Relying Parties to reject responses containing unsolicited extensions.

The updated specification text now states:

"Client platforms MAY enact local policy that sets additional authenticator extensions or client extensions and thus cause values to appear in the authenticator extension outputs or client extension outputs that were not originally specified as part of options.extensions. Relying Parties MUST be prepared to handle such situations, whether it be to ignore the unsolicited extensions or reject the attestation. The Relying Party can make this decision based on local policy and the extensions in use." 

This means Authelia is free to choose the "ignore" policy for unsolicited extension outputs, and the go-webauthn library already provides the UnsolicitedOutputPolicyIgnore option to do exactly that.

Workaround for users

Until this is fixed upstream, the only workaround is to build Authelia from source with the one-line patch described above, or to use Chrome/Firefox on macOS and accept that Safari/iOS users cannot log in via Passkey.

Generative AI

Yes

Pre-Submission Checklist

  • I agree to follow the Code of Conduct

  • This is a bug report and not a support request

  • I have read the security policy and this bug report is not a security issue or security related issue

  • I have either included the complete configuration file or I am sure it's unrelated to the configuration

  • I have either included the complete debug / trace logs or the output of the build-info command if the logs are not relevant

  • I have provided all of the required information in full with the only alteration being reasonable sanitization in accordance with the Troubleshooting Sanitization reference guide

  • I have checked for related proxy or application logs and included them if available

  • I have checked for related issues and checked the documentation