{"version":3,"file":"routes.mjs","names":["APIError","ERROR_CODES"],"sources":["../../../src/plugins/email-otp/routes.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { deprecate } from \"@better-auth/core/utils/deprecate\";\nimport * as z from \"zod\";\nimport {\n\tAPIError,\n\tgetSessionFromCtx,\n\tsensitiveSessionMiddleware,\n} from \"../../api\";\nimport { setCookieCache, setSessionCookie } from \"../../cookies\";\nimport { generateRandomString, symmetricDecrypt } from \"../../crypto\";\nimport { parseUserInput, parseUserOutput } from \"../../db/schema\";\nimport { getDate } from \"../../utils/date\";\nimport { EMAIL_OTP_ERROR_CODES as ERROR_CODES } from \"./error-codes\";\nimport { storeOTP, tryReuseOTP, verifyStoredOTP } from \"./otp-token\";\nimport type { EmailOTPOptions, RequiredEmailOTPOptions } from \"./types\";\nimport { splitAtLastColon, toOTPIdentifier } from \"./utils\";\n\nconst types = [\n\t\"email-verification\",\n\t\"sign-in\",\n\t\"forget-password\",\n\t\"change-email\",\n] as const;\n\n/**\n * Resolves the OTP to send: reuses an existing one if possible,\n * otherwise generates and stores a new one.\n *\n * @internal\n */\nasync function resolveOTP(\n\tctx: GenericEndpointContext,\n\topts: RequiredEmailOTPOptions,\n\temail: string,\n\ttype: (typeof types)[number],\n): Promise<string> {\n\tconst identifier = toOTPIdentifier(type, email);\n\n\tif (opts.resendStrategy === \"reuse\") {\n\t\tconst reused = await tryReuseOTP(ctx, opts, identifier);\n\t\tif (reused) return reused;\n\t}\n\n\tconst otp =\n\t\topts.generateOTP({ email, type }, ctx) || defaultOTPGenerator(opts);\n\tconst storedOTP = await storeOTP(ctx, opts, otp);\n\n\tawait ctx.context.internalAdapter\n\t\t.createVerificationValue({\n\t\t\tvalue: `${storedOTP}:0`,\n\t\t\tidentifier,\n\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t})\n\t\t.catch(async () => {\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\tidentifier,\n\t\t\t);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\tidentifier,\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\n\t\t});\n\n\treturn otp;\n}\n\nconst sendVerificationOTPBodySchema = z.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address to send the OTP\",\n\t}),\n\ttype: z.enum(types).meta({\n\t\tdescription: \"Type of the OTP\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/send-verification-otp`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.sendVerificationOTP`\n *\n * **client:**\n * `authClient.emailOtp.sendVerificationOtp`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-send-verification-otp)\n */\nexport const sendVerificationOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/send-verification-otp\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: sendVerificationOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"sendEmailVerificationOTP\",\n\t\t\t\t\tdescription: \"Send a verification OTP to an email\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (!opts?.sendVerificationOTP) {\n\t\t\t\tctx.context.logger.error(\"send email verification is not implemented\");\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"send email verification is not implemented\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst email = ctx.body.email.toLowerCase();\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\n\t\t\t// Enforce using the correct endpoint for change email OTP\n\t\t\tif (ctx.body.type === \"change-email\") {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\"Use the /email-otp/request-email-change endpoint to send OTP for changing email\",\n\t\t\t\t);\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Invalid OTP type\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst identifier = toOTPIdentifier(ctx.body.type, email);\n\t\t\tconst otp = await resolveOTP(ctx, opts, email, ctx.body.type);\n\n\t\t\tconst shouldSendOTP = ctx.body.type === \"sign-in\" && !opts.disableSignUp;\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user && !shouldSendOTP) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t);\n\t\t\t\treturn ctx.json({ success: true });\n\t\t\t}\n\n\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\topts.sendVerificationOTP({ email, otp, type: ctx.body.type }, ctx),\n\t\t\t);\n\t\t\treturn ctx.json({ success: true });\n\t\t},\n\t);\n\nconst createVerificationOTPBodySchema = z.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address to send the OTP\",\n\t}),\n\ttype: z.enum(types).meta({\n\t\trequired: true,\n\t\tdescription: \"Type of the OTP\",\n\t}),\n});\n\nexport const createVerificationOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: createVerificationOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"createEmailVerificationOTP\",\n\t\t\t\t\tdescription: \"Create a verification OTP for an email\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.body.email.toLowerCase();\n\t\t\tconst otp =\n\t\t\t\topts.generateOTP({ email, type: ctx.body.type }, ctx) ||\n\t\t\t\tdefaultOTPGenerator(opts);\n\t\t\tconst storedOTP = await storeOTP(ctx, opts, otp);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\tidentifier: toOTPIdentifier(ctx.body.type, email),\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\n\t\t\treturn otp;\n\t\t},\n\t);\n\nconst getVerificationOTPBodySchema = z.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address the OTP was sent to\",\n\t}),\n\ttype: z.enum(types).meta({\n\t\trequired: true,\n\t\tdescription: \"Type of the OTP\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * GET `/email-otp/get-verification-otp`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.getVerificationOTP`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-get-verification-otp)\n */\nexport const getVerificationOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: getVerificationOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getEmailVerificationOTP\",\n\t\t\t\t\tdescription: \"Get a verification OTP for an email\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"OTP retrieved successfully or not found/expired\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\totp: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The stored OTP, or null if not found or expired\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"otp\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.query.email.toLowerCase();\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\ttoOTPIdentifier(ctx.query.type, email),\n\t\t\t\t);\n\t\t\tif (!verificationValue || verificationValue.expiresAt < new Date()) {\n\t\t\t\treturn ctx.json({\n\t\t\t\t\totp: null,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (\n\t\t\t\topts.storeOTP === \"hashed\" ||\n\t\t\t\t(typeof opts.storeOTP === \"object\" && \"hash\" in opts.storeOTP)\n\t\t\t) {\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"OTP is hashed, cannot return the plain text OTP\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst [storedOtp, _attempts] = splitAtLastColon(verificationValue.value);\n\t\t\tlet otp = storedOtp;\n\t\t\tif (opts.storeOTP === \"encrypted\") {\n\t\t\t\totp = await symmetricDecrypt({\n\t\t\t\t\tkey: ctx.context.secretConfig,\n\t\t\t\t\tdata: storedOtp,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (typeof opts.storeOTP === \"object\" && \"decrypt\" in opts.storeOTP) {\n\t\t\t\totp = await opts.storeOTP.decrypt(storedOtp);\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\totp,\n\t\t\t});\n\t\t},\n\t);\n\nconst checkVerificationOTPBodySchema = z.object({\n\temail: z.string().meta({\n\t\tdescription: \"Email address the OTP was sent to\",\n\t}),\n\ttype: z.enum(types).meta({\n\t\trequired: true,\n\t\tdescription: \"Type of the OTP\",\n\t}),\n\totp: z.string().meta({\n\t\trequired: true,\n\t\tdescription: \"OTP to verify\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * GET `/email-otp/check-verification-otp`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.checkVerificationOTP`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-check-verification-otp)\n */\nexport const checkVerificationOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/check-verification-otp\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: checkVerificationOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"verifyEmailWithOTP\",\n\t\t\t\t\tdescription: \"Verify an email with an OTP\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.body.email.toLowerCase();\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.USER_NOT_FOUND);\n\t\t\t}\n\t\t\tconst identifier = toOTPIdentifier(ctx.body.type, email);\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(identifier);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.OTP_EXPIRED);\n\t\t\t}\n\n\t\t\tconst [otpValue, attempts] = splitAtLastColon(verificationValue.value);\n\t\t\tconst allowedAttempts = opts?.allowedAttempts || 3;\n\t\t\tif (attempts && parseInt(attempts) >= allowedAttempts) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"FORBIDDEN\", ERROR_CODES.TOO_MANY_ATTEMPTS);\n\t\t\t}\n\t\t\tconst verified = await verifyStoredOTP(ctx, opts, otpValue, ctx.body.otp);\n\t\t\tif (!verified) {\n\t\t\t\tawait ctx.context.internalAdapter.updateVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: `${otpValue}:${parseInt(attempts || \"0\") + 1}`,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n\nconst verifyEmailOTPBodySchema = z.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address to verify\",\n\t}),\n\totp: z.string().meta({\n\t\trequired: true,\n\t\tdescription: \"OTP to verify\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/verify-email`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.verifyEmailOTP`\n *\n * **client:**\n * `authClient.emailOtp.verifyEmail`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-verify-email)\n */\nexport const verifyEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/verify-email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyEmailOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Verify email with OTP\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the verification was successful\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [true],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Session token if autoSignInAfterVerification is enabled, otherwise null\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"status\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.body.email.toLowerCase();\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\n\t\t\t// Use atomic verification to prevent race conditions\n\t\t\tawait atomicVerifyOTP(\n\t\t\t\tctx,\n\t\t\t\topts,\n\t\t\t\ttoOTPIdentifier(\"email-verification\", email),\n\t\t\t\tctx.body.otp,\n\t\t\t);\n\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\t/**\n\t\t\t\t * safe to leak the existence of a user, given the user has already the OTP from the\n\t\t\t\t * email\n\t\t\t\t */\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.USER_NOT_FOUND);\n\t\t\t}\n\t\t\tif (ctx.context.options.emailVerification?.beforeEmailVerification) {\n\t\t\t\tawait ctx.context.options.emailVerification.beforeEmailVerification(\n\t\t\t\t\tuser.user,\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUser(\n\t\t\t\tuser.user.id,\n\t\t\t\t{\n\t\t\t\t\temail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tawait ctx.context.options.emailVerification?.afterEmailVerification?.(\n\t\t\t\tupdatedUser,\n\t\t\t\tctx.request,\n\t\t\t);\n\n\t\t\tif (ctx.context.options.emailVerification?.autoSignInAfterVerification) {\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tupdatedUser.id,\n\t\t\t\t);\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: updatedUser,\n\t\t\t\t});\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tstatus: true,\n\t\t\t\t\ttoken: session.token,\n\t\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst currentSession = await getSessionFromCtx(ctx);\n\t\t\tif (currentSession && updatedUser.emailVerified) {\n\t\t\t\tconst dontRememberMeCookie = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\t\t\t\tawait setCookieCache(\n\t\t\t\t\tctx,\n\t\t\t\t\t{\n\t\t\t\t\t\tsession: currentSession.session,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...currentSession.user,\n\t\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t!!dontRememberMeCookie,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t\ttoken: null,\n\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t});\n\t\t},\n\t);\n\nconst signInEmailOTPBodySchema = z\n\t.object({\n\t\temail: z.string({}).meta({\n\t\t\tdescription: \"Email address to sign in\",\n\t\t}),\n\t\totp: z.string().meta({\n\t\t\trequired: true,\n\t\t\tdescription: \"OTP sent to the email\",\n\t\t}),\n\t\tname: z\n\t\t\t.string()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t'User display name. Only used if the user is registering for the first time. Eg: \"my-name\"',\n\t\t\t})\n\t\t\t.optional(),\n\t\timage: z\n\t\t\t.string()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"User profile image URL. Only used if the user is registering for the first time.\",\n\t\t\t})\n\t\t\t.optional(),\n\t})\n\t.and(z.record(z.string(), z.any()));\n\n/**\n * ### Endpoint\n *\n * POST `/sign-in/email-otp`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.signInEmailOTP`\n *\n * **client:**\n * `authClient.signIn.emailOtp`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-sign-in-email-otp)\n */\nexport const signInEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/email-otp\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: signInEmailOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signInWithEmailOTP\",\n\t\t\t\t\tdescription: \"Sign in with email and OTP\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Session token for the authenticated session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { email: rawEmail, otp, name, image, ...rest } = ctx.body;\n\t\t\tconst email = rawEmail.toLowerCase();\n\n\t\t\t// Use atomic verification to prevent race conditions\n\t\t\tawait atomicVerifyOTP(ctx, opts, toOTPIdentifier(\"sign-in\", email), otp);\n\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tif (opts.disableSignUp) {\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t\t}\n\t\t\t\tconst additionalFields = parseUserInput(\n\t\t\t\t\tctx.context.options,\n\t\t\t\t\trest,\n\t\t\t\t\t\"create\",\n\t\t\t\t);\n\t\t\t\tconst newUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\t...additionalFields,\n\t\t\t\t\temail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t\tname: name || \"\",\n\t\t\t\t\timage,\n\t\t\t\t});\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tnewUser.id,\n\t\t\t\t);\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: newUser,\n\t\t\t\t});\n\t\t\t\treturn ctx.json({\n\t\t\t\t\ttoken: session.token,\n\t\t\t\t\tuser: parseUserOutput(ctx.context.options, newUser),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!user.user.emailVerified) {\n\t\t\t\tawait ctx.context.internalAdapter.updateUser(user.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tuser.user.id,\n\t\t\t);\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession,\n\t\t\t\tuser: user.user,\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\ttoken: session.token,\n\t\t\t\tuser: parseUserOutput(ctx.context.options, user.user),\n\t\t\t});\n\t\t},\n\t);\n\nconst requestPasswordResetEmailOTPBodySchema = z.object({\n\temail: z.string().meta({\n\t\tdescription: \"Email address to send the OTP\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/request-password-reset`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.requestPasswordResetEmailOTP`\n *\n * **client:**\n * `authClient.emailOtp.requestPasswordReset`\n *\n * @see [Read our docs to learn more.](https://www.better-auth.com/docs/plugins/email-otp#reset-password-with-otp)\n */\nexport const requestPasswordResetEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/request-password-reset\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: requestPasswordResetEmailOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"requestPasswordResetWithEmailOTP\",\n\t\t\t\t\tdescription: \"Request password reset with email and OTP\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the OTP was sent successfully\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.body.email;\n\t\t\tconst identifier = toOTPIdentifier(\"forget-password\", email);\n\t\t\tconst otp = await resolveOTP(ctx, opts, email, \"forget-password\");\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t);\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\topts.sendVerificationOTP(\n\t\t\t\t\t{\n\t\t\t\t\t\temail,\n\t\t\t\t\t\totp,\n\t\t\t\t\t\ttype: \"forget-password\",\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n\nconst forgetPasswordEmailOTPBodySchema = z.object({\n\temail: z.string().meta({\n\t\tdescription: \"Email address to send the OTP\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/forget-password/email-otp`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.forgetPasswordEmailOTP`\n *\n * **client:**\n * `authClient.forgetPassword.emailOtp`\n *\n * @deprecated Use `/email-otp/request-password-reset` instead.\n * @see [Read our docs to learn more.](https://www.better-auth.com/docs/plugins/email-otp#reset-password-with-otp)\n */\nexport const forgetPasswordEmailOTP = (opts: RequiredEmailOTPOptions) => {\n\tconst warnDeprecation = deprecate(\n\t\t() => {},\n\t\t'The \"/forget-password/email-otp\" endpoint is deprecated. ' +\n\t\t\t'Please use \"/email-otp/request-password-reset\" instead. ' +\n\t\t\t\"This endpoint will be removed in the next major version.\",\n\t);\n\n\treturn createAuthEndpoint(\n\t\t\"/forget-password/email-otp\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: forgetPasswordEmailOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"forgetPasswordWithEmailOTP\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Deprecated: Use /email-otp/request-password-reset instead.\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the OTP was sent successfully\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\twarnDeprecation();\n\t\t\tconst email = ctx.body.email;\n\t\t\tconst identifier = toOTPIdentifier(\"forget-password\", email);\n\t\t\tconst otp = await resolveOTP(ctx, opts, email, \"forget-password\");\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tidentifier,\n\t\t\t\t);\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\topts.sendVerificationOTP(\n\t\t\t\t\t{\n\t\t\t\t\t\temail,\n\t\t\t\t\t\totp,\n\t\t\t\t\t\ttype: \"forget-password\",\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n};\n\nconst resetPasswordEmailOTPBodySchema = z.object({\n\temail: z.string().meta({\n\t\tdescription: \"Email address to reset the password\",\n\t}),\n\totp: z.string().meta({\n\t\tdescription: \"OTP sent to the email\",\n\t}),\n\tpassword: z.string().meta({\n\t\tdescription: \"New password\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/reset-password`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.resetPasswordEmailOTP`\n *\n * **client:**\n * `authClient.emailOtp.resetPassword`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-reset-password)\n */\nexport const resetPasswordEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/reset-password\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: resetPasswordEmailOTPBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"resetPasswordWithEmailOTP\",\n\t\t\t\t\tdescription: \"Reset password with email and OTP\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst email = ctx.body.email;\n\n\t\t\t// Use atomic verification to prevent race conditions\n\t\t\tawait atomicVerifyOTP(\n\t\t\t\tctx,\n\t\t\t\topts,\n\t\t\t\ttoOTPIdentifier(\"forget-password\", email),\n\t\t\t\tctx.body.otp,\n\t\t\t);\n\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t});\n\t\t\tif (!user) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.USER_NOT_FOUND);\n\t\t\t}\n\t\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\t\tif (ctx.body.password.length < minPasswordLength) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);\n\t\t\t}\n\t\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\t\t\tif (ctx.body.password.length > maxPasswordLength) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.PASSWORD_TOO_LONG);\n\t\t\t}\n\t\t\tconst passwordHash = await ctx.context.password.hash(ctx.body.password);\n\t\t\tconst account = user.accounts?.find(\n\t\t\t\t(account) => account.providerId === \"credential\",\n\t\t\t);\n\t\t\tif (!account) {\n\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: user.user.id,\n\t\t\t\t\tproviderId: \"credential\",\n\t\t\t\t\taccountId: user.user.id,\n\t\t\t\t\tpassword: passwordHash,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait ctx.context.internalAdapter.updatePassword(\n\t\t\t\t\tuser.user.id,\n\t\t\t\t\tpasswordHash,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (ctx.context.options.emailAndPassword?.onPasswordReset) {\n\t\t\t\tawait ctx.context.options.emailAndPassword.onPasswordReset(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t},\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!user.user.emailVerified) {\n\t\t\t\tawait ctx.context.internalAdapter.updateUser(user.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteSessions(user.user.id);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n\nconst requestEmailChangeEmailOTPBodySchema = z.object({\n\tnewEmail: z.string().meta({\n\t\tdescription: \"New email address to send the OTP\",\n\t}),\n\totp: z.string().optional().meta({\n\t\tdescription:\n\t\t\t\"OTP sent to the current email. This is required if changeEmail.verifyCurrentEmail option is set to true\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/request-email-change`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.requestEmailChangeEmailOTP`\n *\n * **client:**\n * `authClient.emailOtp.requestEmailChange`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#change-email-with-otp)\n */\nexport const requestEmailChangeEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/request-email-change\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: requestEmailChangeEmailOTPBodySchema,\n\t\t\tuse: [sensitiveSessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"requestEmailChangeWithEmailOTP\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Request email change with verification OTP sent to the new email\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (!opts.changeEmail?.enabled) {\n\t\t\t\tctx.context.logger.error(\"Change email with OTP is disabled.\");\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Change email with OTP is disabled\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst email = ctx.context.session.user.email.toLowerCase();\n\t\t\tconst newEmail = ctx.body.newEmail.toLowerCase();\n\t\t\tconst isValidEmail = z.email().safeParse(newEmail);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\t\t\tif (newEmail === email) {\n\t\t\t\tctx.context.logger.error(\"Email is the same\");\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email is the same\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (opts.changeEmail?.verifyCurrentEmail) {\n\t\t\t\tif (!ctx.body.otp) {\n\t\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: \"OTP is required to verify current email\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst currentEmailVerificationValue =\n\t\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t\ttoOTPIdentifier(\"email-verification\", email),\n\t\t\t\t\t);\n\t\t\t\tif (!currentEmailVerificationValue) {\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t\t}\n\t\t\t\tconst currentEmailIdentifier = toOTPIdentifier(\n\t\t\t\t\t\"email-verification\",\n\t\t\t\t\temail,\n\t\t\t\t);\n\t\t\t\tif (currentEmailVerificationValue.expiresAt < new Date()) {\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\tcurrentEmailIdentifier,\n\t\t\t\t\t);\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.OTP_EXPIRED);\n\t\t\t\t}\n\n\t\t\t\tconst [otpValue, attempts] = splitAtLastColon(\n\t\t\t\t\tcurrentEmailVerificationValue.value,\n\t\t\t\t);\n\t\t\t\tconst allowedAttempts = opts?.allowedAttempts || 3;\n\t\t\t\tif (attempts && parseInt(attempts) >= allowedAttempts) {\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\tcurrentEmailIdentifier,\n\t\t\t\t\t);\n\t\t\t\t\tthrow APIError.from(\"FORBIDDEN\", ERROR_CODES.TOO_MANY_ATTEMPTS);\n\t\t\t\t}\n\n\t\t\t\tconst verified = await verifyStoredOTP(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\totpValue,\n\t\t\t\t\tctx.body.otp,\n\t\t\t\t);\n\t\t\t\tif (!verified) {\n\t\t\t\t\tawait ctx.context.internalAdapter.updateVerificationByIdentifier(\n\t\t\t\t\t\tcurrentEmailIdentifier,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: `${otpValue}:${parseInt(attempts || \"0\") + 1}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t\t}\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tcurrentEmailIdentifier,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (ctx.body.otp) {\n\t\t\t\t\tctx.context.logger.warn(\n\t\t\t\t\t\t\"OTP provided but not required for verifying current email. \" +\n\t\t\t\t\t\t\t\"If you want to require OTP verification for current email, \" +\n\t\t\t\t\t\t\t\"please set the changeEmail.verifyCurrentEmail option to true in the configuration\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst otp =\n\t\t\t\topts.generateOTP({ email: newEmail, type: \"change-email\" }, ctx) ||\n\t\t\t\tdefaultOTPGenerator(opts);\n\t\t\tconst storedOTP = await storeOTP(ctx, opts, otp);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\tidentifier: toOTPIdentifier(\"change-email\", `${email}-${newEmail}`),\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\n\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(newEmail);\n\t\t\tif (user) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\ttoOTPIdentifier(\"change-email\", `${email}-${newEmail}`),\n\t\t\t\t);\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\topts.sendVerificationOTP(\n\t\t\t\t\t{\n\t\t\t\t\t\temail: newEmail,\n\t\t\t\t\t\totp,\n\t\t\t\t\t\ttype: \"change-email\",\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n\nconst changeEmailEmailOTPBodySchema = z.object({\n\tnewEmail: z.string().meta({\n\t\tdescription: \"New email address to verify and change to\",\n\t}),\n\totp: z.string().meta({\n\t\tdescription: \"OTP sent to the new email\",\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/email-otp/change-email`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.changeEmailEmailOTP`\n *\n * **client:**\n * `authClient.emailOtp.changeEmail`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#change-email-with-otp)\n */\nexport const changeEmailEmailOTP = (opts: RequiredEmailOTPOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/email-otp/change-email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: changeEmailEmailOTPBodySchema,\n\t\t\tuse: [sensitiveSessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"changeEmailWithEmailOTP\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Verify new email with OTP and change the email if verification is successful\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (!opts.changeEmail?.enabled) {\n\t\t\t\tctx.context.logger.error(\"Change email with OTP is disabled.\");\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Change email with OTP is disabled\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst session = ctx.context.session;\n\n\t\t\tconst email = session.user.email.toLowerCase();\n\t\t\tconst newEmail = ctx.body.newEmail.toLowerCase();\n\t\t\tconst isValidNewEmail = z.email().safeParse(newEmail);\n\t\t\tif (!isValidNewEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\t\t\tif (newEmail === email) {\n\t\t\t\tctx.context.logger.error(\"Email is the same\");\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email is the same\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\ttoOTPIdentifier(\"change-email\", `${email}-${newEmail}`),\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t}\n\t\t\tconst changeEmailIdentifier = toOTPIdentifier(\n\t\t\t\t\"change-email\",\n\t\t\t\t`${email}-${newEmail}`,\n\t\t\t);\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tchangeEmailIdentifier,\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.OTP_EXPIRED);\n\t\t\t}\n\n\t\t\tconst [otpValue, attempts] = splitAtLastColon(verificationValue.value);\n\t\t\tconst allowedAttempts = opts?.allowedAttempts || 3;\n\t\t\tif (attempts && parseInt(attempts) >= allowedAttempts) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tchangeEmailIdentifier,\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"FORBIDDEN\", ERROR_CODES.TOO_MANY_ATTEMPTS);\n\t\t\t}\n\n\t\t\tconst verified = await verifyStoredOTP(ctx, opts, otpValue, ctx.body.otp);\n\t\t\tif (!verified) {\n\t\t\t\tawait ctx.context.internalAdapter.updateVerificationByIdentifier(\n\t\t\t\t\tchangeEmailIdentifier,\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: `${otpValue}:${parseInt(attempts || \"0\") + 1}`,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\tchangeEmailIdentifier,\n\t\t\t);\n\n\t\t\tconst currentUser =\n\t\t\t\tawait ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!currentUser) {\n\t\t\t\t/**\n\t\t\t\t * safe to leak the existence of a user as a valid OTP has been provided\n\t\t\t\t */\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.USER_NOT_FOUND);\n\t\t\t}\n\n\t\t\tconst existingUserWithNewEmail =\n\t\t\t\tawait ctx.context.internalAdapter.findUserByEmail(newEmail);\n\t\t\tif (existingUserWithNewEmail) {\n\t\t\t\t/**\n\t\t\t\t * safe to leak the existence of a user as a valid OTP has been provided\n\t\t\t\t */\n\t\t\t\tthrow APIError.fromStatus(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email already in use\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (ctx.context.options.emailVerification?.beforeEmailVerification) {\n\t\t\t\tawait ctx.context.options.emailVerification.beforeEmailVerification(\n\t\t\t\t\tcurrentUser.user,\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUser(\n\t\t\t\tcurrentUser.user.id,\n\t\t\t\t{\n\t\t\t\t\temail: newEmail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (ctx.context.options.emailVerification?.afterEmailVerification) {\n\t\t\t\tawait ctx.context.options.emailVerification.afterEmailVerification(\n\t\t\t\t\tupdatedUser,\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession: session.session,\n\t\t\t\tuser: {\n\t\t\t\t\t...session.user,\n\t\t\t\t\temail: newEmail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: true,\n\t\t\t});\n\t\t},\n\t);\n\nconst defaultOTPGenerator = (options: EmailOTPOptions) =>\n\tgenerateRandomString(options.otpLength ?? 6, \"0-9\");\n\n/**\n * Atomically verifies OTP with race condition protection.\n * Deletes token before verification to prevent concurrent reuse.\n * Re-creates token with incremented attempts on failure.\n */\nasync function atomicVerifyOTP(\n\tctx: GenericEndpointContext,\n\topts: RequiredEmailOTPOptions,\n\tidentifier: string,\n\tprovidedOTP: string,\n): Promise<void> {\n\tconst verificationValue =\n\t\tawait ctx.context.internalAdapter.findVerificationValue(identifier);\n\n\tif (!verificationValue) {\n\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t}\n\n\tif (verificationValue.expiresAt < new Date()) {\n\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\tidentifier,\n\t\t);\n\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.OTP_EXPIRED);\n\t}\n\n\tconst [otpValue, attempts] = splitAtLastColon(verificationValue.value);\n\tconst allowedAttempts = opts?.allowedAttempts || 3;\n\n\tif (attempts && parseInt(attempts) >= allowedAttempts) {\n\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\tidentifier,\n\t\t);\n\t\tthrow APIError.from(\"FORBIDDEN\", ERROR_CODES.TOO_MANY_ATTEMPTS);\n\t}\n\n\t// Atomically delete token before verification to prevent race condition\n\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);\n\n\tconst verified = await verifyStoredOTP(ctx, opts, otpValue, providedOTP);\n\n\tif (!verified) {\n\t\t// Re-create with incremented attempts\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: `${otpValue}:${parseInt(attempts || \"0\") + 1}`,\n\t\t\tidentifier,\n\t\t\texpiresAt: verificationValue.expiresAt,\n\t\t});\n\t\tthrow APIError.from(\"BAD_REQUEST\", ERROR_CODES.INVALID_OTP);\n\t}\n}\n"],"mappings":"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"}