nextauthjs/next-auth · error · AuthError

Invalid WebAuthn Registration response

Error message

Invalid WebAuthn Registration response

What it means

verifyRegister validates the WebAuthn registration (attestation) response shape before verification. It throws when data is missing, not an object, or lacks a string `id` property — the credential ID needed to normalize and verify the registration.

Source

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

export async function verifyRegister(
  options: InternalOptions<WebAuthnProviderType>,
  request: RequestInternal,
  resCookies: Cookie[]
): Promise<{ account: Account; user: User; authenticator: Authenticator }> {
  const { provider } = options

  // Get WebAuthn response from request body
  const data =
    request.body && typeof request.body.data === "string"
      ? (JSON.parse(request.body.data) as unknown)
      : undefined
  if (
    !data ||
    typeof data !== "object" ||
    !("id" in data) ||
    typeof data.id !== "string"
  ) {
    throw new AuthError("Invalid WebAuthn Registration response")
  }

  // Get challenge from request cookies
  const { challenge: expectedChallenge, registerData: user } =
    await webauthnChallenge.use(options, request.cookies, resCookies)
  if (!user) {
    throw new AuthError(
      "Missing user registration data in WebAuthn challenge cookie"
    )
  }

  // Verify the response
  let verification: VerifiedRegistrationResponse
  try {
    const relayingParty = provider.getRelayingParty(options, request)
    verification = await provider.simpleWebAuthn.verifyRegistrationResponse({
      ...provider.verifyRegistrationOptions,
      expectedChallenge,

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Ensure the client sends the full attestation response including the string `id` from navigator.credentials.create()
  2. Parse the request body as JSON before passing it to verifyRegister
  3. Log the payload to confirm the id field exists and is a string
  4. Check that your registration client library emits spec-compliant attestation objects

Example fix

// before
verifyRegister(searchParams) // no credential payload
// after
const data = await request.json()
if (typeof data.id === "string") verifyRegister(data)
Defensive patterns

Strategy: type-guard

Validate before calling

const data = await request.json()
if (!data || typeof data !== 'object' || typeof data.id !== 'string') {
  return new Response('Invalid attestation', { status: 400 })
}

Type guard

function isValidAttestation(d: unknown): d is { id: string; [k: string]: unknown } {
  return !!d && typeof d === 'object' && 'id' in d && typeof (d as any).id === 'string'
}

Try / catch

try {
  await verifyRegister(data)
} catch (e) {
  if (e instanceof AuthError && /Invalid WebAuthn Registration response/.test(e.message)) {
    return new Response('Bad request', { status: 400 })
  }
  throw e
}

Prevention

When it happens

Trigger: Calling verifyRegister (via the `verified` action) with a null/non-object payload or an attestation response missing its string `id` field.

Common situations: Client attestation truncated or serialized incorrectly; body parsed as text; custom registration client omitting `id`; request forwarded without the credential payload.

Related errors


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