Bug description
Passkeys do not work in Safari, neither creating nor signing in with one. Both flows work in Chrome against the same server, same account and same Statamic install.
Creating (/cp/passkeys → "Create passkey"): the button shows its spinner indefinitely. The Touch ID / Face ID prompt never appears.
Signing in (login screen → "Passkey"): same result — nothing happens, no prompt.
Safari's console logs this warning from SimpleWebAuthn:
startRegistration() was not called correctly. It will try to continue with the provided
options, but this call should be refactored to use the expected call structure instead.
See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge
Nothing is written to laravel.log — the failure is entirely client side.
What I ruled out
- Relying party / origin:
APP_URL matches the origin exactly (https://staging.example.com).
- Storage: a passkey created in Chrome is confirmed to land in the iCloud Keychain, so the credential store is reachable.
- Licence: same install, Pro trial, works in Chrome.
- Server errors: no entries in
laravel.log for the attempts.
Likely cause
Both flows fetch their options first (cp/passkeys/create for registration, cp/passkeys/options for authentication) and call startRegistration() / startAuthentication() afterwards, in the promise continuation.
Safari requires the WebAuthn ceremony to be started directly from the user gesture. Once an awaited request sits between the click and the call, Safari drops the gesture and the ceremony never starts — silently, which matches the endless spinner. Chrome does not enforce this.
The usual fix is to pass the options promise into the ceremony rather than awaiting it first, so the call happens synchronously within the gesture.
How to reproduce
- Open the CP in Safari (macOS 15, Safari 18).
- Go to Users → Passkeys → "Create passkey".
- The spinner starts, no system prompt appears, nothing completes.
- Repeat in Chrome — the prompt appears and the passkey is created.
Environment
- Statamic 6.27.2 (Pro, trial)
- Laravel 13.25, PHP 8.5
- web-auth/webauthn-lib 5.3.5
- Safari on macOS (fails) / Chrome on macOS (works)
- Eloquent user driver,
statamic.webauthn at defaults
Bug description
Passkeys do not work in Safari, neither creating nor signing in with one. Both flows work in Chrome against the same server, same account and same Statamic install.
Creating (
/cp/passkeys→ "Create passkey"): the button shows its spinner indefinitely. The Touch ID / Face ID prompt never appears.Signing in (login screen → "Passkey"): same result — nothing happens, no prompt.
Safari's console logs this warning from SimpleWebAuthn:
Nothing is written to
laravel.log— the failure is entirely client side.What I ruled out
APP_URLmatches the origin exactly (https://staging.example.com).laravel.logfor the attempts.Likely cause
Both flows fetch their options first (
cp/passkeys/createfor registration,cp/passkeys/optionsfor authentication) and callstartRegistration()/startAuthentication()afterwards, in the promise continuation.Safari requires the WebAuthn ceremony to be started directly from the user gesture. Once an
awaited request sits between the click and the call, Safari drops the gesture and the ceremony never starts — silently, which matches the endless spinner. Chrome does not enforce this.The usual fix is to pass the options promise into the ceremony rather than awaiting it first, so the call happens synchronously within the gesture.
How to reproduce
Environment
statamic.webauthnat defaults