nextauthjs/next-auth · error · WebAuthnVerificationError

WebAuthn authentication response could not be verified

Error message

WebAuthn authentication response could not be verified

What it means

The @simplewebauthn/server verifyAuthenticationResponse returned verified:false, meaning the assertion failed cryptographic or challenge verification. The library wraps this as a WebAuthnVerificationError.

Source

Thrown at packages/core/src/lib/utils/webauthn-utils.ts:264

  try {
    const relayingParty = provider.getRelayingParty(options, request)
    verification = await provider.simpleWebAuthn.verifyAuthenticationResponse({
      ...provider.verifyAuthenticationOptions,
      expectedChallenge,
      response: data as AuthenticationResponseJSON,
      authenticator: fromAdapterAuthenticator(authenticator),
      expectedOrigin: relayingParty.origin,
      expectedRPID: relayingParty.id,
    })
  } catch (e: any) {
    throw new WebAuthnVerificationError(e)
  }

  const { verified, authenticationInfo } = verification

  // Make sure the response was verified
  if (!verified) {
    throw new WebAuthnVerificationError(
      "WebAuthn authentication response could not be verified"
    )
  }

  // Update authenticator counter
  try {
    const { newCounter } = authenticationInfo
    await adapter.updateAuthenticatorCounter(
      authenticator.credentialID,
      newCounter
    )
  } catch (e: any) {
    throw new AdapterError(
      `Failed to update authenticator counter. This may cause future authentication attempts to fail. ${JSON.stringify(
        {
          credentialID,
          oldCounter: authenticator.counter,
          newCounter: authenticationInfo.newCounter,

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Verify WebAuthnProvider rpID and origin match the domain the client used
  2. Ensure the challenge cookie from startAuthentication still exists and matches at verify time
  3. Confirm the authenticator record's publicKey matches the credential being used
  4. Check @simplewebauthn/server version compatibility with the response format

Example fix

// before
WebAuthnProvider({ id: "example.com" }) // client on localhost
// after
WebAuthnProvider({ id: "localhost", origin: "http://localhost:3000" })
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check config consistency
console.assert(provider.rpID === new URL(clientOrigin).hostname, 'rpID must match client origin')

Try / catch

try {
  await verifyAuthenticate(data)
} catch (e) {
  if (e instanceof WebAuthnVerificationError) {
    // reject login, clear challenge cookie, log for security review
    return new Response('Verification failed', { status: 401 })
  }
  throw e
}

Prevention

When it happens

Trigger: verifyAuthenticate receives an assertion whose challenge does not match the stored cookie challenge, origin/rpID mismatch, wrong public key for the credential, or a tampered signature.

Common situations: rpID or origin misconfigured between environments (localhost vs production domain); challenge cookie expired or cleared before verification; multiple transports altering the assertion bytes; clock/session issues invalidating the stored challenge.

Understand the failure class

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/b84eb4cc28175946. Report an issue: GitHub.