{"record":{"id":"3ddbbf408b8cc59d","repo":"nextauthjs/next-auth","slug":"invalid-webauthn-registration-response","errorCode":null,"errorMessage":"Invalid WebAuthn Registration response","messagePattern":"Invalid WebAuthn Registration response","errorType":"exception","errorClass":"AuthError","httpStatus":null,"severity":"error","filePath":"packages/core/src/lib/utils/webauthn-utils.ts","lineNumber":338,"sourceCode":"export async function verifyRegister(\n  options: InternalOptions<WebAuthnProviderType>,\n  request: RequestInternal,\n  resCookies: Cookie[]\n): Promise<{ account: Account; user: User; authenticator: Authenticator }> {\n  const { provider } = options\n\n  // Get WebAuthn response from request body\n  const data =\n    request.body && typeof request.body.data === \"string\"\n      ? (JSON.parse(request.body.data) as unknown)\n      : undefined\n  if (\n    !data ||\n    typeof data !== \"object\" ||\n    !(\"id\" in data) ||\n    typeof data.id !== \"string\"\n  ) {\n    throw new AuthError(\"Invalid WebAuthn Registration response\")\n  }\n\n  // Get challenge from request cookies\n  const { challenge: expectedChallenge, registerData: user } =\n    await webauthnChallenge.use(options, request.cookies, resCookies)\n  if (!user) {\n    throw new AuthError(\n      \"Missing user registration data in WebAuthn challenge cookie\"\n    )\n  }\n\n  // Verify the response\n  let verification: VerifiedRegistrationResponse\n  try {\n    const relayingParty = provider.getRelayingParty(options, request)\n    verification = await provider.simpleWebAuthn.verifyRegistrationResponse({\n      ...provider.verifyRegistrationOptions,\n      expectedChallenge,","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/utils/webauthn-utils.ts#L320-L356","documentation":"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.","triggerScenarios":"Calling verifyRegister (via the `verified` action) with a null/non-object payload or an attestation response missing its string `id` field.","commonSituations":"Client attestation truncated or serialized incorrectly; body parsed as text; custom registration client omitting `id`; request forwarded without the credential payload.","solutions":["Ensure the client sends the full attestation response including the string `id` from navigator.credentials.create()","Parse the request body as JSON before passing it to verifyRegister","Log the payload to confirm the id field exists and is a string","Check that your registration client library emits spec-compliant attestation objects"],"exampleFix":"// before\nverifyRegister(searchParams) // no credential payload\n// after\nconst data = await request.json()\nif (typeof data.id === \"string\") verifyRegister(data)","handlingStrategy":"type-guard","validationCode":"const data = await request.json()\nif (!data || typeof data !== 'object' || typeof data.id !== 'string') {\n  return new Response('Invalid attestation', { status: 400 })\n}","typeGuard":"function isValidAttestation(d: unknown): d is { id: string; [k: string]: unknown } {\n  return !!d && typeof d === 'object' && 'id' in d && typeof (d as any).id === 'string'\n}","tryCatchPattern":"try {\n  await verifyRegister(data)\n} catch (e) {\n  if (e instanceof AuthError && /Invalid WebAuthn Registration response/.test(e.message)) {\n    return new Response('Bad request', { status: 400 })\n  }\n  throw e\n}","preventionTips":["Use the official client registration helper to construct the attestation","Ensure the route parses JSON bodies","Validate payloads with a schema library at the edge","Log and reject malformed registrations early"],"tags":["webauthn","input-validation","registration","malformed-response"],"backgroundTag":"invalid-webauthn-response","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}