nextauthjs/next-auth · error · WebAuthnVerificationError
WebAuthn registration response could not be verified
Error message
WebAuthn registration response could not be verified
What it means
The attestation response shape and challenge data were accepted, but @simplewebauthn/server's verifyRegistrationResponse returned verified:false or missing registrationInfo, so the registration cannot be trusted. Thrown as a WebAuthnVerificationError.
Source
Thrown at packages/core/src/lib/utils/webauthn-utils.ts:367
// Verify the response
let verification: VerifiedRegistrationResponse
try {
const relayingParty = provider.getRelayingParty(options, request)
verification = await provider.simpleWebAuthn.verifyRegistrationResponse({
...provider.verifyRegistrationOptions,
expectedChallenge,
response: data as RegistrationResponseJSON,
expectedOrigin: relayingParty.origin,
expectedRPID: relayingParty.id,
})
} catch (e: any) {
throw new WebAuthnVerificationError(e)
}
// Make sure the response was verified
if (!verification.verified || !verification.registrationInfo) {
throw new WebAuthnVerificationError(
"WebAuthn registration response could not be verified"
)
}
// Build a new account
const account = {
providerAccountId: toBase64(verification.registrationInfo.credentialID),
provider: options.provider.id,
type: provider.type,
}
// Build a new authenticator
const authenticator = {
providerAccountId: account.providerAccountId,
counter: verification.registrationInfo.counter,
credentialID: toBase64(verification.registrationInfo.credentialID),
credentialPublicKey: toBase64(
verification.registrationInfo.credentialPublicKeyView on GitHub (pinned to a1a16a5a77)
Solutions
- Align WebAuthnProvider rpID and origin with the actual client origin
- Ensure the challenge cookie from startRegistration is intact and unchanged at verify time
- Check @simplewebauthn/server version supports the client's attestation format
- Test on a platform/browser that supports the configured authenticatorSelection requirements
Example fix
// before
WebAuthnProvider({ id: "prod.example.com" }) // testing on localhost
// after
WebAuthnProvider({ id: "localhost", origin: "http://localhost:3000" }) Defensive patterns
Strategy: try-catch
Validate before calling
// environment pre-check
console.assert(provider.rpID === location.hostname, 'rpID must match the client origin')
console.assert(document.cookie.includes('next-auth.webauthn-challenge'), 'challenge cookie must exist') Try / catch
try {
await verifyRegister(data)
} catch (e) {
if (e instanceof WebAuthnVerificationError) {
// clear cookies, log attestation failure, restart registration
return new Response('Attestation verification failed', { status: 400 })
}
throw e
} Prevention
- Match rpID/origin to each deployment environment
- Pin compatible @simplewebauthn/server versions with the provider
- Test passkey creation on all target browsers/platforms
- Never skip the challenge cookie in proxied deployments
When it happens
Trigger: verifyRegister receives an attestation that fails verification — challenge mismatch with the cookie, origin/rpID mismatch, unsupported attestation format, or device not eligible for passkey creation.
Common situations: rpID/origin configured for a different domain than the client; challenge cookie expired or replaced between start and verify; attestation format (e.g. 'none' vs 'packed') unsupported by the @simplewebauthn/server version; browser/platform restrictions (e.g. no platform authenticator available).
Related errors
- WebAuthn authentication response could not be verified
- Invalid WebAuthn Registration response
- Missing user registration data in WebAuthn challenge cookie
- Authenticator not found.
- Authenticator not found.
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/f92039e72a436a5d.
Report an issue: GitHub.