{"record":{"id":"229903b0e41d9859","repo":"nextauthjs/next-auth","slug":"accessdenied-229903","errorCode":null,"errorMessage":"AccessDenied","messagePattern":"AccessDenied","errorType":"exception","errorClass":"AccessDenied","httpStatus":null,"severity":"error","filePath":"packages/core/src/lib/actions/signin/send-token.ts","lineNumber":39,"sourceCode":"  const defaultUser = { id: crypto.randomUUID(), email, emailVerified: null }\n  const user = (await adapter!.getUserByEmail(email)) ?? defaultUser\n\n  const account = {\n    providerAccountId: email,\n    userId: user.id,\n    type: \"email\",\n    provider: provider.id,\n  } satisfies Account\n\n  let authorized\n  try {\n    authorized = await callbacks.signIn({\n      user,\n      account,\n      email: { verificationRequest: true },\n    })\n  } catch (e) {\n    throw new AccessDenied(e as Error)\n  }\n  if (!authorized) throw new AccessDenied(\"AccessDenied\")\n  if (typeof authorized === \"string\") {\n    return {\n      redirect: await callbacks.redirect({\n        url: authorized,\n        baseUrl: options.url.origin,\n      }),\n    }\n  }\n\n  const { callbackUrl, theme } = options\n  const token =\n    (await provider.generateVerificationToken?.()) ?? randomString(32)\n\n  const ONE_DAY_IN_SECONDS = 86400\n  const expires = new Date(\n    Date.now() + (provider.maxAge ?? ONE_DAY_IN_SECONDS) * 1000","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/actions/signin/send-token.ts#L21-L57","documentation":"In the email/magic-link sign-in flow, after verifying the token Auth.js calls the signIn callback with the user, account, and verificationRequest flag. If that callback returns a falsy value, sign-in is refused and an AccessDenied error with message 'AccessDenied' is thrown.","triggerScenarios":"The developer-supplied signIn callback explicitly returns false or returns undefined/void (implicit undefined) during an email verification request, so authorized is falsy and the error is thrown at send-token.ts:39.","commonSituations":"Implementing a custom signIn callback with an early `return false` for unverified domains or blocked users; forgetting to return true at the end of the callback (all branches must return); allow-list logic accidentally rejecting the requesting email; copy-pasted callback that only handles credentials provider cases.","solutions":["Make the signIn callback return true for allowed email sign-ins — ensure every code path returns an explicit boolean","If you intend to deny specific addresses, return a redirect URL string instead of false to send the user to a friendly 'access denied' page","Log the inputs (user.email, verificationRequest) inside the callback to see which rule rejects the request","Review domain allow-list logic for case sensitivity or typos that unintentionally fail the check"],"exampleFix":"// before\ncallbacks: {\n  async signIn({ user, email }) {\n    if (email?.verificationRequest && !user.email?.endsWith('@company.com')) return false;\n    // falls through returning undefined -> AccessDenied\n  },\n}\n// after\ncallbacks: {\n  async signIn({ user, email }) {\n    if (email?.verificationRequest && !user.email?.endsWith('@company.com')) return false;\n    return true;\n  },\n}","handlingStrategy":"validation","validationCode":"// Audit your signIn callback: every branch must return an explicit boolean\nfunction auditSignInCallback(cb: (...a: any[]) => unknown) {\n  // ensure no path falls through returning undefined\n  return cb;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await signIn('email', { email });\n} catch (e) {\n  if (e instanceof AccessDenied) {\n    // show 'check your email' or an access-denied page instead of a raw error\n  }\n}","preventionTips":["Always `return true` at the end of the signIn callback — never rely on implicit undefined","Return a redirect URL string instead of false when you want a friendly denial page","Log decisions inside the callback to trace which rule rejects sign-ins","Test email sign-in with addresses inside and outside your allow-list"],"tags":["oauth","access-denied","callbacks","configuration"],"backgroundTag":"signin-callback-denied","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}