better-auth 1.4.18 → 1.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/drizzle-adapter/drizzle-adapter.mjs +37 -5
- package/dist/adapters/drizzle-adapter/drizzle-adapter.mjs.map +1 -1
- package/dist/adapters/kysely-adapter/kysely-adapter.mjs +13 -3
- package/dist/adapters/kysely-adapter/kysely-adapter.mjs.map +1 -1
- package/dist/adapters/memory-adapter/memory-adapter.mjs +21 -17
- package/dist/adapters/memory-adapter/memory-adapter.mjs.map +1 -1
- package/dist/adapters/mongodb-adapter/mongodb-adapter.mjs +12 -1
- package/dist/adapters/mongodb-adapter/mongodb-adapter.mjs.map +1 -1
- package/dist/adapters/prisma-adapter/prisma-adapter.mjs +2 -2
- package/dist/adapters/prisma-adapter/prisma-adapter.mjs.map +1 -1
- package/dist/api/index.d.mts +407 -407
- package/dist/api/routes/account.d.mts +11 -11
- package/dist/api/routes/account.mjs +1 -1
- package/dist/api/routes/account.mjs.map +1 -1
- package/dist/api/routes/callback.d.mts +2 -2
- package/dist/api/routes/callback.mjs +1 -1
- package/dist/api/routes/callback.mjs.map +1 -1
- package/dist/api/routes/email-verification.d.mts +4 -4
- package/dist/api/routes/email-verification.mjs +1 -1
- package/dist/api/routes/email-verification.mjs.map +1 -1
- package/dist/api/routes/error.d.mts +2 -2
- package/dist/api/routes/ok.d.mts +2 -2
- package/dist/api/routes/password.d.mts +7 -7
- package/dist/api/routes/session.d.mts +14 -14
- package/dist/api/routes/sign-in.d.mts +4 -4
- package/dist/api/routes/sign-out.d.mts +2 -2
- package/dist/api/routes/sign-up.d.mts +3 -3
- package/dist/api/routes/update-user.d.mts +13 -13
- package/dist/api/routes/update-user.mjs +1 -1
- package/dist/api/routes/update-user.mjs.map +1 -1
- package/dist/client/react/index.d.mts +13 -13
- package/dist/client/svelte/index.d.mts +15 -15
- package/dist/client/vanilla.d.mts +15 -15
- package/dist/client/vue/index.d.mts +15 -15
- package/dist/context/create-context.mjs +1 -1
- package/dist/context/create-context.mjs.map +1 -1
- package/dist/cookies/index.d.mts +6 -6
- package/dist/cookies/index.mjs +5 -8
- package/dist/cookies/index.mjs.map +1 -1
- package/dist/db/field.d.mts +10 -10
- package/dist/db/field.mjs.map +1 -1
- package/dist/db/internal-adapter.mjs +1 -1
- package/dist/db/internal-adapter.mjs.map +1 -1
- package/dist/integrations/next-js.d.mts +4 -4
- package/dist/integrations/svelte-kit.d.mts +2 -2
- package/dist/integrations/tanstack-start-solid.d.mts +4 -4
- package/dist/integrations/tanstack-start.d.mts +4 -4
- package/dist/plugins/access/types.d.mts +1 -1
- package/dist/plugins/admin/admin.d.mts +114 -119
- package/dist/plugins/admin/admin.mjs +1 -1
- package/dist/plugins/admin/admin.mjs.map +1 -1
- package/dist/plugins/admin/routes.mjs +1 -1
- package/dist/plugins/admin/routes.mjs.map +1 -1
- package/dist/plugins/anonymous/index.d.mts +7 -7
- package/dist/plugins/api-key/index.d.mts +95 -80
- package/dist/plugins/api-key/routes/verify-api-key.mjs +1 -0
- package/dist/plugins/api-key/routes/verify-api-key.mjs.map +1 -1
- package/dist/plugins/bearer/index.d.mts +6 -6
- package/dist/plugins/captcha/index.d.mts +2 -2
- package/dist/plugins/custom-session/index.d.mts +5 -5
- package/dist/plugins/custom-session/index.mjs +13 -5
- package/dist/plugins/custom-session/index.mjs.map +1 -1
- package/dist/plugins/device-authorization/index.d.mts +6 -6
- package/dist/plugins/email-otp/index.d.mts +16 -16
- package/dist/plugins/email-otp/routes.mjs +1 -1
- package/dist/plugins/email-otp/routes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/error-codes.mjs +3 -1
- package/dist/plugins/generic-oauth/error-codes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/index.d.mts +32 -29
- package/dist/plugins/generic-oauth/index.mjs +8 -0
- package/dist/plugins/generic-oauth/index.mjs.map +1 -1
- package/dist/plugins/generic-oauth/routes.mjs +19 -2
- package/dist/plugins/generic-oauth/routes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/types.d.mts +14 -0
- package/dist/plugins/haveibeenpwned/index.d.mts +3 -3
- package/dist/plugins/jwt/client.d.mts +2 -2
- package/dist/plugins/jwt/index.d.mts +9 -9
- package/dist/plugins/last-login-method/index.d.mts +4 -4
- package/dist/plugins/magic-link/index.d.mts +4 -4
- package/dist/plugins/mcp/authorize.mjs +1 -1
- package/dist/plugins/mcp/authorize.mjs.map +1 -1
- package/dist/plugins/mcp/index.d.mts +10 -10
- package/dist/plugins/multi-session/index.d.mts +9 -9
- package/dist/plugins/oauth-proxy/index.d.mts +8 -8
- package/dist/plugins/oidc-provider/authorize.mjs +1 -1
- package/dist/plugins/oidc-provider/authorize.mjs.map +1 -1
- package/dist/plugins/oidc-provider/index.d.mts +15 -15
- package/dist/plugins/one-tap/client.d.mts +5 -5
- package/dist/plugins/one-tap/index.d.mts +2 -2
- package/dist/plugins/one-time-token/index.d.mts +5 -5
- package/dist/plugins/open-api/index.d.mts +3 -3
- package/dist/plugins/organization/client.d.mts +9 -9
- package/dist/plugins/organization/error-codes.d.mts +1 -0
- package/dist/plugins/organization/error-codes.mjs +2 -1
- package/dist/plugins/organization/error-codes.mjs.map +1 -1
- package/dist/plugins/organization/organization.d.mts +4 -4
- package/dist/plugins/organization/routes/crud-access-control.d.mts +22 -22
- package/dist/plugins/organization/routes/crud-access-control.mjs +22 -0
- package/dist/plugins/organization/routes/crud-access-control.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-invites.d.mts +70 -70
- package/dist/plugins/organization/routes/crud-invites.mjs +0 -4
- package/dist/plugins/organization/routes/crud-invites.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-members.d.mts +67 -67
- package/dist/plugins/organization/routes/crud-org.d.mts +59 -59
- package/dist/plugins/organization/routes/crud-team.d.mts +79 -79
- package/dist/plugins/phone-number/index.d.mts +33 -33
- package/dist/plugins/phone-number/routes.mjs +6 -2
- package/dist/plugins/phone-number/routes.mjs.map +1 -1
- package/dist/plugins/siwe/index.d.mts +3 -3
- package/dist/plugins/two-factor/backup-codes/index.d.mts +5 -5
- package/dist/plugins/two-factor/client.d.mts +2 -2
- package/dist/plugins/two-factor/index.d.mts +18 -18
- package/dist/plugins/two-factor/otp/index.d.mts +3 -3
- package/dist/plugins/two-factor/totp/index.d.mts +5 -5
- package/dist/plugins/username/index.d.mts +12 -12
- package/dist/plugins/username/schema.d.mts +3 -3
- package/dist/test-utils/test-instance.d.mts +1242 -1242
- package/package.json +3 -3
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { EmailOTPOptions } from "./types.mjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _better_auth_core5 from "@better-auth/core";
|
|
3
3
|
import * as _better_auth_core_db0 from "@better-auth/core/db";
|
|
4
|
-
import * as
|
|
4
|
+
import * as better_call20 from "better-call";
|
|
5
5
|
import * as zod0 from "zod";
|
|
6
6
|
import * as zod_v4_core0 from "zod/v4/core";
|
|
7
7
|
|
|
8
8
|
//#region src/plugins/email-otp/index.d.ts
|
|
9
9
|
declare const emailOTP: (options: EmailOTPOptions) => {
|
|
10
10
|
id: "email-otp";
|
|
11
|
-
init(ctx:
|
|
11
|
+
init(ctx: _better_auth_core5.AuthContext): {
|
|
12
12
|
options: {
|
|
13
13
|
emailVerification: {
|
|
14
14
|
sendVerificationEmail(data: {
|
|
@@ -20,7 +20,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
20
20
|
};
|
|
21
21
|
} | undefined;
|
|
22
22
|
endpoints: {
|
|
23
|
-
sendVerificationOTP:
|
|
23
|
+
sendVerificationOTP: better_call20.StrictEndpoint<"/email-otp/send-verification-otp", {
|
|
24
24
|
method: "POST";
|
|
25
25
|
body: zod0.ZodObject<{
|
|
26
26
|
email: zod0.ZodString;
|
|
@@ -56,7 +56,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
56
56
|
}, {
|
|
57
57
|
success: boolean;
|
|
58
58
|
}>;
|
|
59
|
-
createVerificationOTP:
|
|
59
|
+
createVerificationOTP: better_call20.StrictEndpoint<string, {
|
|
60
60
|
method: "POST";
|
|
61
61
|
body: zod0.ZodObject<{
|
|
62
62
|
email: zod0.ZodString;
|
|
@@ -85,7 +85,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
87
|
}, string>;
|
|
88
|
-
getVerificationOTP:
|
|
88
|
+
getVerificationOTP: better_call20.StrictEndpoint<string, {
|
|
89
89
|
method: "GET";
|
|
90
90
|
query: zod0.ZodObject<{
|
|
91
91
|
email: zod0.ZodString;
|
|
@@ -126,7 +126,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
126
126
|
} | {
|
|
127
127
|
otp: string;
|
|
128
128
|
}>;
|
|
129
|
-
checkVerificationOTP:
|
|
129
|
+
checkVerificationOTP: better_call20.StrictEndpoint<"/email-otp/check-verification-otp", {
|
|
130
130
|
method: "POST";
|
|
131
131
|
body: zod0.ZodObject<{
|
|
132
132
|
email: zod0.ZodString;
|
|
@@ -163,7 +163,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
163
163
|
}, {
|
|
164
164
|
success: boolean;
|
|
165
165
|
}>;
|
|
166
|
-
verifyEmailOTP:
|
|
166
|
+
verifyEmailOTP: better_call20.StrictEndpoint<"/email-otp/verify-email", {
|
|
167
167
|
method: "POST";
|
|
168
168
|
body: zod0.ZodObject<{
|
|
169
169
|
email: zod0.ZodString;
|
|
@@ -227,7 +227,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
227
227
|
image?: string | null | undefined;
|
|
228
228
|
} & Record<string, any>;
|
|
229
229
|
}>;
|
|
230
|
-
signInEmailOTP:
|
|
230
|
+
signInEmailOTP: better_call20.StrictEndpoint<"/sign-in/email-otp", {
|
|
231
231
|
method: "POST";
|
|
232
232
|
body: zod0.ZodObject<{
|
|
233
233
|
email: zod0.ZodString;
|
|
@@ -273,7 +273,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
273
273
|
image?: string | null | undefined;
|
|
274
274
|
};
|
|
275
275
|
}>;
|
|
276
|
-
requestPasswordResetEmailOTP:
|
|
276
|
+
requestPasswordResetEmailOTP: better_call20.StrictEndpoint<"/email-otp/request-password-reset", {
|
|
277
277
|
method: "POST";
|
|
278
278
|
body: zod0.ZodObject<{
|
|
279
279
|
email: zod0.ZodString;
|
|
@@ -305,7 +305,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
305
305
|
}, {
|
|
306
306
|
success: boolean;
|
|
307
307
|
}>;
|
|
308
|
-
forgetPasswordEmailOTP:
|
|
308
|
+
forgetPasswordEmailOTP: better_call20.StrictEndpoint<"/forget-password/email-otp", {
|
|
309
309
|
method: "POST";
|
|
310
310
|
body: zod0.ZodObject<{
|
|
311
311
|
email: zod0.ZodString;
|
|
@@ -337,7 +337,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
337
337
|
}, {
|
|
338
338
|
success: boolean;
|
|
339
339
|
}>;
|
|
340
|
-
resetPasswordEmailOTP:
|
|
340
|
+
resetPasswordEmailOTP: better_call20.StrictEndpoint<"/email-otp/reset-password", {
|
|
341
341
|
method: "POST";
|
|
342
342
|
body: zod0.ZodObject<{
|
|
343
343
|
email: zod0.ZodString;
|
|
@@ -351,10 +351,10 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
351
351
|
responses: {
|
|
352
352
|
200: {
|
|
353
353
|
description: string;
|
|
354
|
-
|
|
354
|
+
content: {
|
|
355
355
|
"application/json": {
|
|
356
356
|
schema: {
|
|
357
|
-
type:
|
|
357
|
+
type: "object";
|
|
358
358
|
properties: {
|
|
359
359
|
success: {
|
|
360
360
|
type: string;
|
|
@@ -373,8 +373,8 @@ declare const emailOTP: (options: EmailOTPOptions) => {
|
|
|
373
373
|
};
|
|
374
374
|
hooks: {
|
|
375
375
|
after: {
|
|
376
|
-
matcher(context:
|
|
377
|
-
handler: (inputContext:
|
|
376
|
+
matcher(context: _better_auth_core5.HookEndpointContext): boolean;
|
|
377
|
+
handler: (inputContext: better_call20.MiddlewareInputContext<better_call20.MiddlewareOptions>) => Promise<void>;
|
|
378
378
|
}[];
|
|
379
379
|
};
|
|
380
380
|
$ERROR_CODES: {
|
|
@@ -579,7 +579,7 @@ const resetPasswordEmailOTP = (opts) => createAuthEndpoint("/email-otp/reset-pas
|
|
|
579
579
|
description: "Reset password with email and OTP",
|
|
580
580
|
responses: { 200: {
|
|
581
581
|
description: "Success",
|
|
582
|
-
|
|
582
|
+
content: { "application/json": { schema: {
|
|
583
583
|
type: "object",
|
|
584
584
|
properties: { success: { type: "boolean" } }
|
|
585
585
|
} } }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.mjs","names":["session"],"sources":["../../../src/plugins/email-otp/routes.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { defineErrorCodes, deprecate } from \"@better-auth/core/utils\";\nimport * as z from \"zod\";\nimport { APIError, getSessionFromCtx } from \"../../api\";\nimport { setCookieCache, setSessionCookie } from \"../../cookies\";\nimport { generateRandomString, symmetricDecrypt } from \"../../crypto\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport { getDate } from \"../../utils/date\";\nimport { storeOTP, verifyStoredOTP } from \"./otp-token\";\nimport type { EmailOTPOptions } from \"./types\";\nimport { splitAtLastColon } from \"./utils\";\n\nconst types = [\"email-verification\", \"sign-in\", \"forget-password\"] as const;\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype RequiredEmailOTPOptions = WithRequired<\n\tEmailOTPOptions,\n\t\"expiresIn\" | \"generateOTP\" | \"storeOTP\"\n>;\n\nexport const ERROR_CODES = defineErrorCodes({\n\tOTP_EXPIRED: \"OTP expired\",\n\tINVALID_OTP: \"Invalid OTP\",\n\tTOO_MANY_ATTEMPTS: \"Too many attempts\",\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 new APIError(\"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 ctx.error(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst otp =\n\t\t\t\topts.generateOTP({ email, type: ctx.body.type }, ctx) ||\n\t\t\t\tdefaultOTPGenerator(opts);\n\n\t\t\tconst storedOTP = await storeOTP(ctx, opts, otp);\n\n\t\t\tawait ctx.context.internalAdapter\n\t\t\t\t.createVerificationValue({\n\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\tidentifier: `${ctx.body.type}-otp-${email}`,\n\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t})\n\t\t\t\t.catch(async (error) => {\n\t\t\t\t\t// might be duplicate key error\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t);\n\t\t\t\t\t//try again\n\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\t\tidentifier: `${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tif (ctx.body.type === \"sign-in\" && !opts.disableSignUp) {\n\t\t\t\t\t// allow\n\t\t\t\t} else {\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\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,\n\t\t\t\t\t\totp,\n\t\t\t\t\t\ttype: ctx.body.type,\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 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: `${ctx.body.type}-otp-${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\t`${ctx.query.type}-otp-${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 new APIError(\"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.secret,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\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 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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`email-verification-otp-${email}`,\n\t\t\t\t);\n\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\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\t\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\t\tupdatedUser,\n\t\t\t\t\tctx.request,\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.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address to sign in\",\n\t}),\n\totp: z.string().meta({\n\t\trequired: true,\n\t\tdescription: \"OTP sent to the email\",\n\t}),\n});\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 = ctx.body.email.toLowerCase();\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`sign-in-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\n\t\t\t}\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst newUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\temail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t\tname: \"\",\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 otp =\n\t\t\t\topts.generateOTP({ email, type: \"forget-password\" }, 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: `forget-password-otp-${email}`,\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\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\t`forget-password-otp-${email}`,\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 otp =\n\t\t\t\topts.generateOTP({ email, type: \"forget-password\" }, 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: `forget-password-otp-${email}`,\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\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\t`forget-password-otp-${email}`,\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\tcontnt: {\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\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`forget-password-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\n\t\t\t}\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_SHORT,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_LONG,\n\t\t\t\t});\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 defaultOTPGenerator = (options: EmailOTPOptions) =>\n\tgenerateRandomString(options.otpLength ?? 6, \"0-9\");\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"routes.mjs","names":["session"],"sources":["../../../src/plugins/email-otp/routes.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { defineErrorCodes, deprecate } from \"@better-auth/core/utils\";\nimport * as z from \"zod\";\nimport { APIError, getSessionFromCtx } from \"../../api\";\nimport { setCookieCache, setSessionCookie } from \"../../cookies\";\nimport { generateRandomString, symmetricDecrypt } from \"../../crypto\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport { getDate } from \"../../utils/date\";\nimport { storeOTP, verifyStoredOTP } from \"./otp-token\";\nimport type { EmailOTPOptions } from \"./types\";\nimport { splitAtLastColon } from \"./utils\";\n\nconst types = [\"email-verification\", \"sign-in\", \"forget-password\"] as const;\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype RequiredEmailOTPOptions = WithRequired<\n\tEmailOTPOptions,\n\t\"expiresIn\" | \"generateOTP\" | \"storeOTP\"\n>;\n\nexport const ERROR_CODES = defineErrorCodes({\n\tOTP_EXPIRED: \"OTP expired\",\n\tINVALID_OTP: \"Invalid OTP\",\n\tTOO_MANY_ATTEMPTS: \"Too many attempts\",\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 new APIError(\"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 ctx.error(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst otp =\n\t\t\t\topts.generateOTP({ email, type: ctx.body.type }, ctx) ||\n\t\t\t\tdefaultOTPGenerator(opts);\n\n\t\t\tconst storedOTP = await storeOTP(ctx, opts, otp);\n\n\t\t\tawait ctx.context.internalAdapter\n\t\t\t\t.createVerificationValue({\n\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\tidentifier: `${ctx.body.type}-otp-${email}`,\n\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t})\n\t\t\t\t.catch(async (error) => {\n\t\t\t\t\t// might be duplicate key error\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t);\n\t\t\t\t\t//try again\n\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\t\tidentifier: `${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tif (ctx.body.type === \"sign-in\" && !opts.disableSignUp) {\n\t\t\t\t\t// allow\n\t\t\t\t} else {\n\t\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\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,\n\t\t\t\t\t\totp,\n\t\t\t\t\t\ttype: ctx.body.type,\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 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: `${ctx.body.type}-otp-${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\t`${ctx.query.type}-otp-${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 new APIError(\"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.secret,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`${ctx.body.type}-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\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 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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`email-verification-otp-${email}`,\n\t\t\t\t);\n\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\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\t\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\t\tupdatedUser,\n\t\t\t\t\tctx.request,\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.object({\n\temail: z.string({}).meta({\n\t\tdescription: \"Email address to sign in\",\n\t}),\n\totp: z.string().meta({\n\t\trequired: true,\n\t\tdescription: \"OTP sent to the email\",\n\t}),\n});\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 = ctx.body.email.toLowerCase();\n\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`sign-in-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\n\t\t\t}\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst newUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\temail,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t\tname: \"\",\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 otp =\n\t\t\t\topts.generateOTP({ email, type: \"forget-password\" }, 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: `forget-password-otp-${email}`,\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\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\t`forget-password-otp-${email}`,\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 otp =\n\t\t\t\topts.generateOTP({ email, type: \"forget-password\" }, 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: `forget-password-otp-${email}`,\n\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t});\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\t`forget-password-otp-${email}`,\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\t\t\tconst verificationValue =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t`forget-password-otp-${email}`,\n\t\t\t\t);\n\t\t\tif (!verificationValue) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (verificationValue.expiresAt < new Date()) {\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.OTP_EXPIRED,\n\t\t\t\t});\n\t\t\t}\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.deleteVerificationValue(\n\t\t\t\t\tverificationValue.id,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: ERROR_CODES.TOO_MANY_ATTEMPTS,\n\t\t\t\t});\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.updateVerificationValue(\n\t\t\t\t\tverificationValue.id,\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.INVALID_OTP,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\tverificationValue.id,\n\t\t\t);\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_NOT_FOUND,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_SHORT,\n\t\t\t\t});\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 new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_LONG,\n\t\t\t\t});\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 defaultOTPGenerator = (options: EmailOTPOptions) =>\n\tgenerateRandomString(options.otpLength ?? 6, \"0-9\");\n"],"mappings":"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"}
|
|
@@ -7,7 +7,9 @@ const GENERIC_OAUTH_ERROR_CODES = defineErrorCodes({
|
|
|
7
7
|
PROVIDER_CONFIG_NOT_FOUND: "No config found for provider",
|
|
8
8
|
PROVIDER_ID_REQUIRED: "Provider ID is required",
|
|
9
9
|
INVALID_OAUTH_CONFIG: "Invalid OAuth configuration.",
|
|
10
|
-
SESSION_REQUIRED: "Session is required"
|
|
10
|
+
SESSION_REQUIRED: "Session is required",
|
|
11
|
+
ISSUER_MISMATCH: "OAuth issuer mismatch. The authorization server issuer does not match the expected value (RFC 9207).",
|
|
12
|
+
ISSUER_MISSING: "OAuth issuer parameter missing. The authorization server did not include the required iss parameter (RFC 9207)."
|
|
11
13
|
});
|
|
12
14
|
|
|
13
15
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-codes.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/error-codes.ts"],"sourcesContent":["import { defineErrorCodes } from \"@better-auth/core/utils\";\n\nexport const GENERIC_OAUTH_ERROR_CODES = defineErrorCodes({\n\tINVALID_OAUTH_CONFIGURATION: \"Invalid OAuth configuration\",\n\tTOKEN_URL_NOT_FOUND: \"Invalid OAuth configuration. Token URL not found.\",\n\tPROVIDER_CONFIG_NOT_FOUND: \"No config found for provider\",\n\tPROVIDER_ID_REQUIRED: \"Provider ID is required\",\n\tINVALID_OAUTH_CONFIG: \"Invalid OAuth configuration.\",\n\tSESSION_REQUIRED: \"Session is required\",\n});\n"],"mappings":";;;AAEA,MAAa,4BAA4B,iBAAiB;CACzD,6BAA6B;CAC7B,qBAAqB;CACrB,2BAA2B;CAC3B,sBAAsB;CACtB,sBAAsB;CACtB,kBAAkB;CAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"error-codes.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/error-codes.ts"],"sourcesContent":["import { defineErrorCodes } from \"@better-auth/core/utils\";\n\nexport const GENERIC_OAUTH_ERROR_CODES = defineErrorCodes({\n\tINVALID_OAUTH_CONFIGURATION: \"Invalid OAuth configuration\",\n\tTOKEN_URL_NOT_FOUND: \"Invalid OAuth configuration. Token URL not found.\",\n\tPROVIDER_CONFIG_NOT_FOUND: \"No config found for provider\",\n\tPROVIDER_ID_REQUIRED: \"Provider ID is required\",\n\tINVALID_OAUTH_CONFIG: \"Invalid OAuth configuration.\",\n\tSESSION_REQUIRED: \"Session is required\",\n\tISSUER_MISMATCH:\n\t\t\"OAuth issuer mismatch. The authorization server issuer does not match the expected value (RFC 9207).\",\n\tISSUER_MISSING:\n\t\t\"OAuth issuer parameter missing. The authorization server did not include the required iss parameter (RFC 9207).\",\n});\n"],"mappings":";;;AAEA,MAAa,4BAA4B,iBAAiB;CACzD,6BAA6B;CAC7B,qBAAqB;CACrB,2BAA2B;CAC3B,sBAAsB;CACtB,sBAAsB;CACtB,kBAAkB;CAClB,iBACC;CACD,gBACC;CACD,CAAC"}
|
|
@@ -12,9 +12,9 @@ import "./providers/index.mjs";
|
|
|
12
12
|
import { AuthContext } from "@better-auth/core";
|
|
13
13
|
import * as _better_auth_core_oauth21 from "@better-auth/core/oauth2";
|
|
14
14
|
import { OAuthProvider } from "@better-auth/core/oauth2";
|
|
15
|
-
import * as
|
|
16
|
-
import * as
|
|
17
|
-
import * as
|
|
15
|
+
import * as better_call234 from "better-call";
|
|
16
|
+
import * as zod468 from "zod";
|
|
17
|
+
import * as zod_v4_core70 from "zod/v4/core";
|
|
18
18
|
|
|
19
19
|
//#region src/plugins/generic-oauth/index.d.ts
|
|
20
20
|
/**
|
|
@@ -36,18 +36,18 @@ declare const genericOAuth: (options: GenericOAuthOptions) => {
|
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
38
|
endpoints: {
|
|
39
|
-
signInWithOAuth2:
|
|
39
|
+
signInWithOAuth2: better_call234.StrictEndpoint<"/sign-in/oauth2", {
|
|
40
40
|
method: "POST";
|
|
41
|
-
body:
|
|
42
|
-
providerId:
|
|
43
|
-
callbackURL:
|
|
44
|
-
errorCallbackURL:
|
|
45
|
-
newUserCallbackURL:
|
|
46
|
-
disableRedirect:
|
|
47
|
-
scopes:
|
|
48
|
-
requestSignUp:
|
|
49
|
-
additionalData:
|
|
50
|
-
},
|
|
41
|
+
body: zod468.ZodObject<{
|
|
42
|
+
providerId: zod468.ZodString;
|
|
43
|
+
callbackURL: zod468.ZodOptional<zod468.ZodString>;
|
|
44
|
+
errorCallbackURL: zod468.ZodOptional<zod468.ZodString>;
|
|
45
|
+
newUserCallbackURL: zod468.ZodOptional<zod468.ZodString>;
|
|
46
|
+
disableRedirect: zod468.ZodOptional<zod468.ZodBoolean>;
|
|
47
|
+
scopes: zod468.ZodOptional<zod468.ZodArray<zod468.ZodString>>;
|
|
48
|
+
requestSignUp: zod468.ZodOptional<zod468.ZodBoolean>;
|
|
49
|
+
additionalData: zod468.ZodOptional<zod468.ZodRecord<zod468.ZodString, zod468.ZodAny>>;
|
|
50
|
+
}, zod_v4_core70.$strip>;
|
|
51
51
|
metadata: {
|
|
52
52
|
openapi: {
|
|
53
53
|
description: string;
|
|
@@ -77,14 +77,15 @@ declare const genericOAuth: (options: GenericOAuthOptions) => {
|
|
|
77
77
|
url: string;
|
|
78
78
|
redirect: boolean;
|
|
79
79
|
}>;
|
|
80
|
-
oAuth2Callback:
|
|
80
|
+
oAuth2Callback: better_call234.StrictEndpoint<"/oauth2/callback/:providerId", {
|
|
81
81
|
method: "GET";
|
|
82
|
-
query:
|
|
83
|
-
code:
|
|
84
|
-
error:
|
|
85
|
-
error_description:
|
|
86
|
-
state:
|
|
87
|
-
|
|
82
|
+
query: zod468.ZodObject<{
|
|
83
|
+
code: zod468.ZodOptional<zod468.ZodString>;
|
|
84
|
+
error: zod468.ZodOptional<zod468.ZodString>;
|
|
85
|
+
error_description: zod468.ZodOptional<zod468.ZodString>;
|
|
86
|
+
state: zod468.ZodOptional<zod468.ZodString>;
|
|
87
|
+
iss: zod468.ZodOptional<zod468.ZodString>;
|
|
88
|
+
}, zod_v4_core70.$strip>;
|
|
88
89
|
metadata: {
|
|
89
90
|
allowedMediaTypes: string[];
|
|
90
91
|
openapi: {
|
|
@@ -110,15 +111,15 @@ declare const genericOAuth: (options: GenericOAuthOptions) => {
|
|
|
110
111
|
scope: "server";
|
|
111
112
|
};
|
|
112
113
|
}, void>;
|
|
113
|
-
oAuth2LinkAccount:
|
|
114
|
+
oAuth2LinkAccount: better_call234.StrictEndpoint<"/oauth2/link", {
|
|
114
115
|
method: "POST";
|
|
115
|
-
body:
|
|
116
|
-
providerId:
|
|
117
|
-
callbackURL:
|
|
118
|
-
scopes:
|
|
119
|
-
errorCallbackURL:
|
|
120
|
-
},
|
|
121
|
-
use: ((inputContext:
|
|
116
|
+
body: zod468.ZodObject<{
|
|
117
|
+
providerId: zod468.ZodString;
|
|
118
|
+
callbackURL: zod468.ZodString;
|
|
119
|
+
scopes: zod468.ZodOptional<zod468.ZodArray<zod468.ZodString>>;
|
|
120
|
+
errorCallbackURL: zod468.ZodOptional<zod468.ZodString>;
|
|
121
|
+
}, zod_v4_core70.$strip>;
|
|
122
|
+
use: ((inputContext: better_call234.MiddlewareInputContext<better_call234.MiddlewareOptions>) => Promise<{
|
|
122
123
|
session: {
|
|
123
124
|
session: Record<string, any> & {
|
|
124
125
|
id: string;
|
|
@@ -184,6 +185,8 @@ declare const genericOAuth: (options: GenericOAuthOptions) => {
|
|
|
184
185
|
readonly PROVIDER_ID_REQUIRED: "Provider ID is required";
|
|
185
186
|
readonly INVALID_OAUTH_CONFIG: "Invalid OAuth configuration.";
|
|
186
187
|
readonly SESSION_REQUIRED: "Session is required";
|
|
188
|
+
readonly ISSUER_MISMATCH: "OAuth issuer mismatch. The authorization server issuer does not match the expected value (RFC 9207).";
|
|
189
|
+
readonly ISSUER_MISSING: "OAuth issuer parameter missing. The authorization server did not include the required iss parameter (RFC 9207).";
|
|
187
190
|
};
|
|
188
191
|
};
|
|
189
192
|
//#endregion
|
|
@@ -19,6 +19,14 @@ import { betterFetch } from "@better-fetch/fetch";
|
|
|
19
19
|
* A generic OAuth plugin that can be used to add OAuth support to any provider
|
|
20
20
|
*/
|
|
21
21
|
const genericOAuth = (options) => {
|
|
22
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
23
|
+
const nonUniqueIds = /* @__PURE__ */ new Set();
|
|
24
|
+
for (const config of options.config) {
|
|
25
|
+
const id = config.providerId;
|
|
26
|
+
if (seenIds.has(id)) nonUniqueIds.add(id);
|
|
27
|
+
seenIds.add(id);
|
|
28
|
+
}
|
|
29
|
+
if (nonUniqueIds.size > 0) console.warn(`Duplicate provider IDs found: ${Array.from(nonUniqueIds).join(", ")}`);
|
|
22
30
|
return {
|
|
23
31
|
id: "generic-oauth",
|
|
24
32
|
init: (ctx) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/index.ts"],"sourcesContent":["import type { AuthContext, BetterAuthPlugin } from \"@better-auth/core\";\nimport type { OAuth2Tokens, OAuthProvider } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport {\n\tgetUserInfo,\n\toAuth2Callback,\n\toAuth2LinkAccount,\n\tsignInWithOAuth2,\n} from \"./routes\";\nimport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\nexport * from \"./providers\";\nexport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\n/**\n * Base type for OAuth provider options.\n * Extracts common fields from GenericOAuthConfig and makes clientSecret required.\n */\nexport type BaseOAuthProviderOptions = Omit<\n\tPick<\n\t\tGenericOAuthConfig,\n\t\t| \"clientId\"\n\t\t| \"clientSecret\"\n\t\t| \"scopes\"\n\t\t| \"redirectURI\"\n\t\t| \"pkce\"\n\t\t| \"disableImplicitSignUp\"\n\t\t| \"disableSignUp\"\n\t\t| \"overrideUserInfo\"\n\t>,\n\t\"clientSecret\"\n> & {\n\t/** OAuth client secret (required for provider options) */\n\tclientSecret: string;\n};\n\n/**\n * A generic OAuth plugin that can be used to add OAuth support to any provider\n */\nexport const genericOAuth = (options: GenericOAuthOptions) => {\n\treturn {\n\t\tid: \"generic-oauth\",\n\t\tinit: (ctx: AuthContext) => {\n\t\t\tconst genericProviders = options.config.map((c) => {\n\t\t\t\tlet finalUserInfoUrl = c.userInfoUrl;\n\t\t\t\treturn {\n\t\t\t\t\tid: c.providerId,\n\t\t\t\t\tname: c.providerId,\n\t\t\t\t\tasync createAuthorizationURL(data: {\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tcodeVerifier: string;\n\t\t\t\t\t\tscopes?: string[] | undefined;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tdisplay?: string | undefined;\n\t\t\t\t\t\tloginHint?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\tlet finalAuthUrl = c.authorizationUrl;\n\t\t\t\t\t\tif (!finalAuthUrl && c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl =\n\t\t\t\t\t\t\t\t\tfinalUserInfoUrl ?? discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalAuthUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn createAuthorizationURL({\n\t\t\t\t\t\t\tid: c.providerId,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\t\t\t\tstate: data.state,\n\t\t\t\t\t\t\tcodeVerifier: c.pkce ? data.codeVerifier : undefined,\n\t\t\t\t\t\t\tscopes: c.scopes || [],\n\t\t\t\t\t\t\tredirectURI: `${ctx.baseURL}/oauth2/callback/${c.providerId}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync validateAuthorizationCode(data: {\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tcodeVerifier?: string | undefined;\n\t\t\t\t\t\tdeviceId?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\t// Use custom getToken if provided\n\t\t\t\t\t\tif (c.getToken) {\n\t\t\t\t\t\t\treturn c.getToken(data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Standard token exchange flow\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validateAuthorizationCode({\n\t\t\t\t\t\t\theaders: c.authorizationHeaders,\n\t\t\t\t\t\t\tcode: data.code,\n\t\t\t\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync refreshAccessToken(\n\t\t\t\t\t\trefreshToken: string,\n\t\t\t\t\t): Promise<OAuth2Tokens> {\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync getUserInfo(tokens: OAuth2Tokens) {\n\t\t\t\t\t\tconst userInfo = c.getUserInfo\n\t\t\t\t\t\t\t? await c.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl);\n\t\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst userMap = await c.mapProfileToUser?.(userInfo);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: userInfo?.id,\n\t\t\t\t\t\t\t\temail: userInfo?.email,\n\t\t\t\t\t\t\t\temailVerified: userInfo?.emailVerified,\n\t\t\t\t\t\t\t\timage: userInfo?.image,\n\t\t\t\t\t\t\t\tname: userInfo?.name,\n\t\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdata: userInfo,\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\toverrideUserInfoOnSignIn: c.overrideUserInfo,\n\t\t\t\t\t},\n\t\t\t\t} as OAuthProvider;\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tsocialProviders: genericProviders.concat(ctx.socialProviders),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsignInWithOAuth2: signInWithOAuth2(options),\n\t\t\toAuth2Callback: oAuth2Callback(options),\n\t\t\toAuth2LinkAccount: oAuth2LinkAccount(options),\n\t\t},\n\t\toptions,\n\t\t$ERROR_CODES: GENERIC_OAUTH_ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/index.ts"],"sourcesContent":["import type { AuthContext, BetterAuthPlugin } from \"@better-auth/core\";\nimport type { OAuth2Tokens, OAuthProvider } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport {\n\tgetUserInfo,\n\toAuth2Callback,\n\toAuth2LinkAccount,\n\tsignInWithOAuth2,\n} from \"./routes\";\nimport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\nexport * from \"./providers\";\nexport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\n/**\n * Base type for OAuth provider options.\n * Extracts common fields from GenericOAuthConfig and makes clientSecret required.\n */\nexport type BaseOAuthProviderOptions = Omit<\n\tPick<\n\t\tGenericOAuthConfig,\n\t\t| \"clientId\"\n\t\t| \"clientSecret\"\n\t\t| \"scopes\"\n\t\t| \"redirectURI\"\n\t\t| \"pkce\"\n\t\t| \"disableImplicitSignUp\"\n\t\t| \"disableSignUp\"\n\t\t| \"overrideUserInfo\"\n\t>,\n\t\"clientSecret\"\n> & {\n\t/** OAuth client secret (required for provider options) */\n\tclientSecret: string;\n};\n\n/**\n * A generic OAuth plugin that can be used to add OAuth support to any provider\n */\nexport const genericOAuth = (options: GenericOAuthOptions) => {\n\tconst seenIds = new Set<string>();\n\tconst nonUniqueIds = new Set<string>();\n\n\tfor (const config of options.config) {\n\t\tconst id = config.providerId;\n\t\tif (seenIds.has(id)) {\n\t\t\tnonUniqueIds.add(id);\n\t\t}\n\t\tseenIds.add(id);\n\t}\n\n\tif (nonUniqueIds.size > 0) {\n\t\tconsole.warn(\n\t\t\t`Duplicate provider IDs found: ${Array.from(nonUniqueIds).join(\", \")}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tid: \"generic-oauth\",\n\t\tinit: (ctx: AuthContext) => {\n\t\t\tconst genericProviders = options.config.map((c) => {\n\t\t\t\tlet finalUserInfoUrl = c.userInfoUrl;\n\t\t\t\treturn {\n\t\t\t\t\tid: c.providerId,\n\t\t\t\t\tname: c.providerId,\n\t\t\t\t\tasync createAuthorizationURL(data: {\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tcodeVerifier: string;\n\t\t\t\t\t\tscopes?: string[] | undefined;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tdisplay?: string | undefined;\n\t\t\t\t\t\tloginHint?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\tlet finalAuthUrl = c.authorizationUrl;\n\t\t\t\t\t\tif (!finalAuthUrl && c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl =\n\t\t\t\t\t\t\t\t\tfinalUserInfoUrl ?? discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalAuthUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn createAuthorizationURL({\n\t\t\t\t\t\t\tid: c.providerId,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\t\t\t\tstate: data.state,\n\t\t\t\t\t\t\tcodeVerifier: c.pkce ? data.codeVerifier : undefined,\n\t\t\t\t\t\t\tscopes: c.scopes || [],\n\t\t\t\t\t\t\tredirectURI: `${ctx.baseURL}/oauth2/callback/${c.providerId}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync validateAuthorizationCode(data: {\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tcodeVerifier?: string | undefined;\n\t\t\t\t\t\tdeviceId?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\t// Use custom getToken if provided\n\t\t\t\t\t\tif (c.getToken) {\n\t\t\t\t\t\t\treturn c.getToken(data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Standard token exchange flow\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validateAuthorizationCode({\n\t\t\t\t\t\t\theaders: c.authorizationHeaders,\n\t\t\t\t\t\t\tcode: data.code,\n\t\t\t\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync refreshAccessToken(\n\t\t\t\t\t\trefreshToken: string,\n\t\t\t\t\t): Promise<OAuth2Tokens> {\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync getUserInfo(tokens: OAuth2Tokens) {\n\t\t\t\t\t\tconst userInfo = c.getUserInfo\n\t\t\t\t\t\t\t? await c.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl);\n\t\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst userMap = await c.mapProfileToUser?.(userInfo);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: userInfo?.id,\n\t\t\t\t\t\t\t\temail: userInfo?.email,\n\t\t\t\t\t\t\t\temailVerified: userInfo?.emailVerified,\n\t\t\t\t\t\t\t\timage: userInfo?.image,\n\t\t\t\t\t\t\t\tname: userInfo?.name,\n\t\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdata: userInfo,\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\toverrideUserInfoOnSignIn: c.overrideUserInfo,\n\t\t\t\t\t},\n\t\t\t\t} as OAuthProvider;\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tsocialProviders: genericProviders.concat(ctx.socialProviders),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsignInWithOAuth2: signInWithOAuth2(options),\n\t\t\toAuth2Callback: oAuth2Callback(options),\n\t\t\toAuth2LinkAccount: oAuth2LinkAccount(options),\n\t\t},\n\t\toptions,\n\t\t$ERROR_CODES: GENERIC_OAUTH_ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":"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"}
|
|
@@ -112,7 +112,8 @@ const OAuth2CallbackQuerySchema = z.object({
|
|
|
112
112
|
code: z.string().meta({ description: "The OAuth2 code" }).optional(),
|
|
113
113
|
error: z.string().meta({ description: "The error message, if any" }).optional(),
|
|
114
114
|
error_description: z.string().meta({ description: "The error description, if any" }).optional(),
|
|
115
|
-
state: z.string().meta({ description: "The state parameter from the OAuth2 request" }).optional()
|
|
115
|
+
state: z.string().meta({ description: "The state parameter from the OAuth2 request" }).optional(),
|
|
116
|
+
iss: z.string().meta({ description: "The issuer identifier" }).optional()
|
|
116
117
|
});
|
|
117
118
|
const oAuth2Callback = (options) => createAuthEndpoint("/oauth2/callback/:providerId", {
|
|
118
119
|
method: "GET",
|
|
@@ -150,6 +151,7 @@ const oAuth2Callback = (options) => createAuthEndpoint("/oauth2/callback/:provid
|
|
|
150
151
|
}
|
|
151
152
|
let finalTokenUrl = providerConfig.tokenUrl;
|
|
152
153
|
let finalUserInfoUrl = providerConfig.userInfoUrl;
|
|
154
|
+
let expectedIssuer = providerConfig.issuer;
|
|
153
155
|
if (providerConfig.discoveryUrl) {
|
|
154
156
|
const discovery = await betterFetch(providerConfig.discoveryUrl, {
|
|
155
157
|
method: "GET",
|
|
@@ -158,6 +160,21 @@ const oAuth2Callback = (options) => createAuthEndpoint("/oauth2/callback/:provid
|
|
|
158
160
|
if (discovery.data) {
|
|
159
161
|
finalTokenUrl = discovery.data.token_endpoint;
|
|
160
162
|
finalUserInfoUrl = discovery.data.userinfo_endpoint;
|
|
163
|
+
if (!expectedIssuer && discovery.data.issuer) expectedIssuer = discovery.data.issuer;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (expectedIssuer) {
|
|
167
|
+
if (ctx.query.iss) {
|
|
168
|
+
if (ctx.query.iss !== expectedIssuer) {
|
|
169
|
+
ctx.context.logger.error("OAuth issuer mismatch", {
|
|
170
|
+
expected: expectedIssuer,
|
|
171
|
+
received: ctx.query.iss
|
|
172
|
+
});
|
|
173
|
+
return redirectOnError("issuer_mismatch");
|
|
174
|
+
}
|
|
175
|
+
} else if (providerConfig.requireIssuerValidation) {
|
|
176
|
+
ctx.context.logger.error("OAuth issuer parameter missing", { expected: expectedIssuer });
|
|
177
|
+
return redirectOnError("issuer_missing");
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
180
|
try {
|
|
@@ -213,7 +230,7 @@ const oAuth2Callback = (options) => createAuthEndpoint("/oauth2/callback/:provid
|
|
|
213
230
|
};
|
|
214
231
|
})();
|
|
215
232
|
if (link) {
|
|
216
|
-
if (ctx.context.options.account?.accountLinking?.allowDifferentEmails !== true && link.email !== userInfo.email) return redirectOnError("email_doesn't_match");
|
|
233
|
+
if (ctx.context.options.account?.accountLinking?.allowDifferentEmails !== true && link.email.toLowerCase() !== userInfo.email.toLowerCase()) return redirectOnError("email_doesn't_match");
|
|
217
234
|
const existingAccount = await ctx.context.internalAdapter.findAccountByProviderId(String(userInfo.id), providerConfig.providerId);
|
|
218
235
|
if (existingAccount) {
|
|
219
236
|
if (existingAccount.userId !== link.userId) return redirectOnError("account_already_linked_to_different_user");
|