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,11 +1,11 @@
|
|
|
1
1
|
import * as _better_auth_core_oauth29 from "@better-auth/core/oauth2";
|
|
2
|
-
import * as
|
|
2
|
+
import * as better_call814 from "better-call";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
|
|
5
5
|
//#region src/api/routes/account.d.ts
|
|
6
|
-
declare const listUserAccounts:
|
|
6
|
+
declare const listUserAccounts: better_call814.StrictEndpoint<"/list-accounts", {
|
|
7
7
|
method: "GET";
|
|
8
|
-
use: ((inputContext:
|
|
8
|
+
use: ((inputContext: better_call814.MiddlewareInputContext<better_call814.MiddlewareOptions>) => Promise<{
|
|
9
9
|
session: {
|
|
10
10
|
session: Record<string, any> & {
|
|
11
11
|
id: string;
|
|
@@ -87,7 +87,7 @@ declare const listUserAccounts: better_call768.StrictEndpoint<"/list-accounts",
|
|
|
87
87
|
providerId: string;
|
|
88
88
|
accountId: string;
|
|
89
89
|
}[]>;
|
|
90
|
-
declare const linkSocialAccount:
|
|
90
|
+
declare const linkSocialAccount: better_call814.StrictEndpoint<"/link-social", {
|
|
91
91
|
method: "POST";
|
|
92
92
|
requireHeaders: true;
|
|
93
93
|
body: z.ZodObject<{
|
|
@@ -106,7 +106,7 @@ declare const linkSocialAccount: better_call768.StrictEndpoint<"/link-social", {
|
|
|
106
106
|
disableRedirect: z.ZodOptional<z.ZodBoolean>;
|
|
107
107
|
additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
108
108
|
}, z.core.$strip>;
|
|
109
|
-
use: ((inputContext:
|
|
109
|
+
use: ((inputContext: better_call814.MiddlewareInputContext<better_call814.MiddlewareOptions>) => Promise<{
|
|
110
110
|
session: {
|
|
111
111
|
session: Record<string, any> & {
|
|
112
112
|
id: string;
|
|
@@ -165,13 +165,13 @@ declare const linkSocialAccount: better_call768.StrictEndpoint<"/link-social", {
|
|
|
165
165
|
url: string;
|
|
166
166
|
redirect: boolean;
|
|
167
167
|
}>;
|
|
168
|
-
declare const unlinkAccount:
|
|
168
|
+
declare const unlinkAccount: better_call814.StrictEndpoint<"/unlink-account", {
|
|
169
169
|
method: "POST";
|
|
170
170
|
body: z.ZodObject<{
|
|
171
171
|
providerId: z.ZodString;
|
|
172
172
|
accountId: z.ZodOptional<z.ZodString>;
|
|
173
173
|
}, z.core.$strip>;
|
|
174
|
-
use: ((inputContext:
|
|
174
|
+
use: ((inputContext: better_call814.MiddlewareInputContext<better_call814.MiddlewareOptions>) => Promise<{
|
|
175
175
|
session: {
|
|
176
176
|
session: Record<string, any> & {
|
|
177
177
|
id: string;
|
|
@@ -219,7 +219,7 @@ declare const unlinkAccount: better_call768.StrictEndpoint<"/unlink-account", {
|
|
|
219
219
|
}, {
|
|
220
220
|
status: boolean;
|
|
221
221
|
}>;
|
|
222
|
-
declare const getAccessToken:
|
|
222
|
+
declare const getAccessToken: better_call814.StrictEndpoint<"/get-access-token", {
|
|
223
223
|
method: "POST";
|
|
224
224
|
body: z.ZodObject<{
|
|
225
225
|
providerId: z.ZodString;
|
|
@@ -267,7 +267,7 @@ declare const getAccessToken: better_call768.StrictEndpoint<"/get-access-token",
|
|
|
267
267
|
scopes: string[];
|
|
268
268
|
idToken: string | undefined;
|
|
269
269
|
}>;
|
|
270
|
-
declare const refreshToken:
|
|
270
|
+
declare const refreshToken: better_call814.StrictEndpoint<"/refresh-token", {
|
|
271
271
|
method: "POST";
|
|
272
272
|
body: z.ZodObject<{
|
|
273
273
|
providerId: z.ZodString;
|
|
@@ -326,9 +326,9 @@ declare const refreshToken: better_call768.StrictEndpoint<"/refresh-token", {
|
|
|
326
326
|
providerId: string;
|
|
327
327
|
accountId: string;
|
|
328
328
|
}>;
|
|
329
|
-
declare const accountInfo:
|
|
329
|
+
declare const accountInfo: better_call814.StrictEndpoint<"/account-info", {
|
|
330
330
|
method: "GET";
|
|
331
|
-
use: ((inputContext:
|
|
331
|
+
use: ((inputContext: better_call814.MiddlewareInputContext<better_call814.MiddlewareOptions>) => Promise<{
|
|
332
332
|
session: {
|
|
333
333
|
session: Record<string, any> & {
|
|
334
334
|
id: string;
|
|
@@ -143,7 +143,7 @@ const linkSocialAccount = createAuthEndpoint("/link-social", {
|
|
|
143
143
|
redirect: false
|
|
144
144
|
});
|
|
145
145
|
if (!(c.context.options.account?.accountLinking?.trustedProviders)?.includes(provider.id) && !linkingUserInfo.user.emailVerified || c.context.options.account?.accountLinking?.enabled === false) throw new APIError("UNAUTHORIZED", { message: "Account not linked - linking not allowed" });
|
|
146
|
-
if (linkingUserInfo.user.email !== session.user.email && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) throw new APIError("UNAUTHORIZED", { message: "Account not linked - different emails not allowed" });
|
|
146
|
+
if (linkingUserInfo.user.email?.toLowerCase() !== session.user.email.toLowerCase() && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) throw new APIError("UNAUTHORIZED", { message: "Account not linked - different emails not allowed" });
|
|
147
147
|
try {
|
|
148
148
|
await c.context.internalAdapter.createAccount({
|
|
149
149
|
userId: session.user.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.mjs","names":["e: any","account: Account | undefined","newTokens: OAuth2Tokens | null","refreshToken","updatedAccount: Record<string, any> | null","refreshToken: string | null | undefined","tokens: OAuth2Tokens"],"sources":["../../../src/api/routes/account.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport type { Account } from \"@better-auth/core/db\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport type { OAuth2Tokens } from \"@better-auth/core/oauth2\";\nimport { SocialProviderListEnum } from \"@better-auth/core/social-providers\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport {\n\tgetAccountCookie,\n\tsetAccountCookie,\n} from \"../../cookies/session-store\";\nimport { parseAccountOutput } from \"../../db/schema\";\nimport { generateState } from \"../../oauth2/state\";\nimport { decryptOAuthToken, setTokenUtil } from \"../../oauth2/utils\";\nimport {\n\tfreshSessionMiddleware,\n\tgetSessionFromCtx,\n\tsessionMiddleware,\n} from \"./session\";\n\nexport const listUserAccounts = createAuthEndpoint(\n\t\"/list-accounts\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"listUserAccounts\",\n\t\t\t\tdescription: \"List all accounts linked to the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: {\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\tid: {\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},\n\t\t\t\t\t\t\t\t\t\t\tproviderId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tcreatedAt: {\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\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tupdatedAt: {\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\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\taccountId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tuserId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tscopes: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\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\t},\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: [\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"providerId\",\n\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"accountId\",\n\t\t\t\t\t\t\t\t\t\t\t\"userId\",\n\t\t\t\t\t\t\t\t\t\t\t\"scopes\",\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},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\t\tconst accounts = await c.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\treturn c.json(\n\t\t\taccounts.map((a) => {\n\t\t\t\tconst { scope, ...parsed } = parseAccountOutput(c.context.options, a);\n\t\t\t\treturn {\n\t\t\t\t\t...parsed,\n\t\t\t\t\tscopes: scope?.split(\",\") || [],\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t},\n);\n\nexport const linkSocialAccount = createAuthEndpoint(\n\t\"/link-social\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * Callback URL to redirect to after the user has signed in.\n\t\t\t */\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to redirect to after the user has signed in\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * OAuth2 provider to use\n\t\t\t */\n\t\t\tprovider: SocialProviderListEnum,\n\t\t\t/**\n\t\t\t * ID Token for direct authentication without redirect\n\t\t\t */\n\t\t\tidToken: z\n\t\t\t\t.object({\n\t\t\t\t\ttoken: z.string(),\n\t\t\t\t\tnonce: z.string().optional(),\n\t\t\t\t\taccessToken: z.string().optional(),\n\t\t\t\t\trefreshToken: z.string().optional(),\n\t\t\t\t\tscopes: z.array(z.string()).optional(),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Whether to allow sign up for new users\n\t\t\t */\n\t\t\trequestSignUp: z.boolean().optional(),\n\t\t\t/**\n\t\t\t * Additional scopes to request when linking the account.\n\t\t\t * This is useful for requesting additional permissions when\n\t\t\t * linking a social account compared to the initial authentication.\n\t\t\t */\n\t\t\tscopes: z\n\t\t\t\t.array(z.string())\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Additional scopes to request from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * The URL to redirect to if there is an error during the link process.\n\t\t\t */\n\t\t\terrorCallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The URL to redirect to if there is an error during the link process\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Disable automatic redirection to the provider\n\t\t\t *\n\t\t\t * This is useful if you want to handle the redirection\n\t\t\t * yourself like in a popup or a different tab.\n\t\t\t */\n\t\t\tdisableRedirect: z\n\t\t\t\t.boolean()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Disable automatic redirection to the provider. Useful for handling the redirection yourself\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Any additional data to pass through the oauth flow.\n\t\t\t */\n\t\t\tadditionalData: z.record(z.string(), z.any()).optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Link a social account to the user\",\n\t\t\t\toperationId: \"linkSocialAccount\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"The authorization URL to redirect the user to\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the user should be redirected to the authorization URL\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\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\trequired: [\"redirect\"],\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},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.body.provider,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t{\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t});\n\t\t}\n\n\t\t// Handle ID Token flow if provided\n\t\tif (c.body.idToken) {\n\t\t\tif (!provider.verifyIdToken) {\n\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\"Provider does not support id token verification\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { token, nonce } = c.body.idToken;\n\t\t\tconst valid = await provider.verifyIdToken(token, nonce);\n\t\t\tif (!valid) {\n\t\t\t\tc.context.logger.error(\"Invalid id token\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst linkingUserInfo = await provider.getUserInfo({\n\t\t\t\tidToken: token,\n\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t});\n\n\t\t\tif (!linkingUserInfo || !linkingUserInfo?.user) {\n\t\t\t\tc.context.logger.error(\"Failed to get user info\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst linkingUserId = String(linkingUserInfo.user.id);\n\n\t\t\tif (!linkingUserInfo.user.email) {\n\t\t\t\tc.context.logger.error(\"User email not found\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst existingAccounts = await c.context.internalAdapter.findAccounts(\n\t\t\t\tsession.user.id,\n\t\t\t);\n\n\t\t\tconst hasBeenLinked = existingAccounts.find(\n\t\t\t\t(a) => a.providerId === provider.id && a.accountId === linkingUserId,\n\t\t\t);\n\n\t\t\tif (hasBeenLinked) {\n\t\t\t\treturn c.json({\n\t\t\t\t\turl: \"\", // this is for type inference\n\t\t\t\t\tstatus: true,\n\t\t\t\t\tredirect: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\n\t\t\tconst isTrustedProvider = trustedProviders?.includes(provider.id);\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !linkingUserInfo.user.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Account not linked - linking not allowed\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tlinkingUserInfo.user.email !== session.user.email &&\n\t\t\t\tc.context.options.account?.accountLinking?.allowDifferentEmails !== true\n\t\t\t) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Account not linked - different emails not allowed\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait c.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\taccountId: linkingUserId,\n\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\tidToken: token,\n\t\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t\t\tscope: c.body.idToken.scopes?.join(\",\"),\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tthrow new APIError(\"EXPECTATION_FAILED\", {\n\t\t\t\t\tmessage: \"Account not linked - unable to create account\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tc.context.options.account?.accountLinking?.updateUserInfoOnLink === true\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\tawait c.context.internalAdapter.updateUser(session.user.id, {\n\t\t\t\t\t\tname: linkingUserInfo.user?.name,\n\t\t\t\t\t\timage: linkingUserInfo.user?.image,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tconsole.warn(\"Could not update user - \" + e.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\turl: \"\", // this is for type inference\n\t\t\t\tstatus: true,\n\t\t\t\tredirect: false,\n\t\t\t});\n\t\t}\n\n\t\t// Handle OAuth flow\n\t\tconst state = await generateState(\n\t\t\tc,\n\t\t\t{\n\t\t\t\tuserId: session.user.id,\n\t\t\t\temail: session.user.email,\n\t\t\t},\n\t\t\tc.body.additionalData,\n\t\t);\n\n\t\tconst url = await provider.createAuthorizationURL({\n\t\t\tstate: state.state,\n\t\t\tcodeVerifier: state.codeVerifier,\n\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\tscopes: c.body.scopes,\n\t\t});\n\n\t\tif (!c.body.disableRedirect) {\n\t\t\tc.setHeader(\"Location\", url.toString());\n\t\t}\n\n\t\treturn c.json({\n\t\t\turl: url.toString(),\n\t\t\tredirect: !c.body.disableRedirect,\n\t\t});\n\t},\n);\nexport const unlinkAccount = createAuthEndpoint(\n\t\"/unlink-account\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string(),\n\t\t\taccountId: z.string().optional(),\n\t\t}),\n\t\tuse: [freshSessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Unlink an account\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\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},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId } = ctx.body;\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tctx.context.session.user.id,\n\t\t);\n\t\tif (\n\t\t\taccounts.length === 1 &&\n\t\t\t!ctx.context.options.account?.accountLinking?.allowUnlinkingAll\n\t\t) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_UNLINK_LAST_ACCOUNT,\n\t\t\t});\n\t\t}\n\t\tconst accountExist = accounts.find((account) =>\n\t\t\taccountId\n\t\t\t\t? account.accountId === accountId && account.providerId === providerId\n\t\t\t\t: account.providerId === providerId,\n\t\t);\n\t\tif (!accountExist) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.ACCOUNT_NOT_FOUND,\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteAccount(accountExist.id);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const getAccessToken = createAuthEndpoint(\n\t\"/get-access-token\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string().meta({\n\t\t\t\tdescription: \"The provider ID for the OAuth provider\",\n\t\t\t}),\n\t\t\taccountId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The account ID associated with the refresh token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tuserId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The user ID associated with the account\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Get a valid access token, doing a refresh if needed\",\n\t\t\t\tresponses: {\n\t\t\t\t\t200: {\n\t\t\t\t\t\tdescription: \"A Valid access token\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttokenType: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tidToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\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\t400: {\n\t\t\t\t\t\tdescription: \"Invalid refresh token or provider configuration\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId, userId } = ctx.body || {};\n\t\tconst req = ctx.request;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (req && !session) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst resolvedUserId = session?.user?.id || userId;\n\t\tif (!resolvedUserId) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tif (!ctx.context.socialProviders.find((p) => p.id === providerId)) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} is not supported.`,\n\t\t\t});\n\t\t}\n\t\tconst accountData = await getAccountCookie(ctx);\n\t\tlet account: Account | undefined = undefined;\n\t\tif (\n\t\t\taccountData &&\n\t\t\tproviderId === accountData.providerId &&\n\t\t\t(!accountId || accountData.id === accountId)\n\t\t) {\n\t\t\taccount = accountData;\n\t\t} else {\n\t\t\tconst accounts =\n\t\t\t\tawait ctx.context.internalAdapter.findAccounts(resolvedUserId);\n\t\t\taccount = accounts.find((acc) =>\n\t\t\t\taccountId\n\t\t\t\t\t? acc.id === accountId && acc.providerId === providerId\n\t\t\t\t\t: acc.providerId === providerId,\n\t\t\t);\n\t\t}\n\n\t\tif (!account) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === providerId,\n\t\t);\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} not found.`,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tlet newTokens: OAuth2Tokens | null = null;\n\t\t\tconst accessTokenExpired =\n\t\t\t\taccount.accessTokenExpiresAt &&\n\t\t\t\tnew Date(account.accessTokenExpiresAt).getTime() - Date.now() < 5_000;\n\t\t\tif (\n\t\t\t\taccount.refreshToken &&\n\t\t\t\taccessTokenExpired &&\n\t\t\t\tprovider.refreshAccessToken\n\t\t\t) {\n\t\t\t\tconst refreshToken = await decryptOAuthToken(\n\t\t\t\t\taccount.refreshToken,\n\t\t\t\t\tctx.context,\n\t\t\t\t);\n\t\t\t\tnewTokens = await provider.refreshAccessToken(refreshToken);\n\t\t\t\tconst updatedData = {\n\t\t\t\t\taccessToken: await setTokenUtil(newTokens.accessToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: newTokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshToken: await setTokenUtil(newTokens.refreshToken, ctx.context),\n\t\t\t\t\trefreshTokenExpiresAt: newTokens.refreshTokenExpiresAt,\n\t\t\t\t};\n\t\t\t\tlet updatedAccount: Record<string, any> | null = null;\n\t\t\t\tif (account.id) {\n\t\t\t\t\tupdatedAccount = await ctx.context.internalAdapter.updateAccount(\n\t\t\t\t\t\taccount.id,\n\t\t\t\t\t\tupdatedData,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (ctx.context.options.account?.storeAccountCookie) {\n\t\t\t\t\tawait setAccountCookie(ctx, {\n\t\t\t\t\t\t...account,\n\t\t\t\t\t\t...(updatedAccount ?? updatedData),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst accessTokenExpiresAt = (() => {\n\t\t\t\tif (newTokens?.accessTokenExpiresAt) {\n\t\t\t\t\tif (typeof newTokens.accessTokenExpiresAt === \"string\") {\n\t\t\t\t\t\treturn new Date(newTokens.accessTokenExpiresAt);\n\t\t\t\t\t}\n\t\t\t\t\treturn newTokens.accessTokenExpiresAt;\n\t\t\t\t}\n\t\t\t\tif (account.accessTokenExpiresAt) {\n\t\t\t\t\tif (typeof account.accessTokenExpiresAt === \"string\") {\n\t\t\t\t\t\treturn new Date(account.accessTokenExpiresAt);\n\t\t\t\t\t}\n\t\t\t\t\treturn account.accessTokenExpiresAt;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})();\n\n\t\t\tconst tokens = {\n\t\t\t\taccessToken:\n\t\t\t\t\tnewTokens?.accessToken ??\n\t\t\t\t\t(await decryptOAuthToken(account.accessToken ?? \"\", ctx.context)),\n\t\t\t\taccessTokenExpiresAt,\n\t\t\t\tscopes: account.scope?.split(\",\") ?? [],\n\t\t\t\tidToken: newTokens?.idToken ?? account.idToken ?? undefined,\n\t\t\t};\n\t\t\treturn ctx.json(tokens);\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to get a valid access token\",\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t},\n);\n\nexport const refreshToken = createAuthEndpoint(\n\t\"/refresh-token\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string().meta({\n\t\t\t\tdescription: \"The provider ID for the OAuth provider\",\n\t\t\t}),\n\t\t\taccountId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The account ID associated with the refresh token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tuserId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The user ID associated with the account\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Refresh the access token using a refresh token\",\n\t\t\t\tresponses: {\n\t\t\t\t\t200: {\n\t\t\t\t\t\tdescription: \"Access token refreshed successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttokenType: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tidToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trefreshToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trefreshTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\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\t400: {\n\t\t\t\t\t\tdescription: \"Invalid refresh token or provider configuration\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId, userId } = ctx.body;\n\t\tconst req = ctx.request;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (req && !session) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst resolvedUserId = session?.user?.id || userId;\n\t\tif (!resolvedUserId) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Either userId or session is required`,\n\t\t\t});\n\t\t}\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === providerId,\n\t\t);\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} not found.`,\n\t\t\t});\n\t\t}\n\t\tif (!provider.refreshAccessToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} does not support token refreshing.`,\n\t\t\t});\n\t\t}\n\n\t\t// Try to read refresh token from cookie first\n\t\tlet account: Account | undefined = undefined;\n\t\tconst accountData = await getAccountCookie(ctx);\n\t\tif (\n\t\t\taccountData &&\n\t\t\t(!providerId || providerId === accountData?.providerId)\n\t\t) {\n\t\t\taccount = accountData;\n\t\t} else {\n\t\t\tconst accounts =\n\t\t\t\tawait ctx.context.internalAdapter.findAccounts(resolvedUserId);\n\t\t\taccount = accounts.find((acc) =>\n\t\t\t\taccountId\n\t\t\t\t\t? acc.id === accountId && acc.providerId === providerId\n\t\t\t\t\t: acc.providerId === providerId,\n\t\t\t);\n\t\t}\n\n\t\tif (!account) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\n\t\tlet refreshToken: string | null | undefined = undefined;\n\t\tif (accountData && providerId === accountData.providerId) {\n\t\t\trefreshToken = accountData.refreshToken ?? undefined;\n\t\t} else {\n\t\t\trefreshToken = account.refreshToken ?? undefined;\n\t\t}\n\n\t\tif (!refreshToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Refresh token not found\",\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst decryptedRefreshToken = await decryptOAuthToken(\n\t\t\t\trefreshToken,\n\t\t\t\tctx.context,\n\t\t\t);\n\t\t\tconst tokens: OAuth2Tokens = await provider.refreshAccessToken(\n\t\t\t\tdecryptedRefreshToken,\n\t\t\t);\n\n\t\t\tif (account.id) {\n\t\t\t\tconst updateData = {\n\t\t\t\t\t...(account || {}),\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\") || account.scope,\n\t\t\t\t\tidToken: tokens.idToken || account.idToken,\n\t\t\t\t};\n\t\t\t\tawait ctx.context.internalAdapter.updateAccount(account.id, updateData);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\taccountData &&\n\t\t\t\tproviderId === accountData.providerId &&\n\t\t\t\tctx.context.options.account?.storeAccountCookie\n\t\t\t) {\n\t\t\t\tconst updateData = {\n\t\t\t\t\t...accountData,\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\") || accountData.scope,\n\t\t\t\t\tidToken: tokens.idToken || accountData.idToken,\n\t\t\t\t};\n\t\t\t\tawait setAccountCookie(ctx, updateData);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\taccessToken: tokens.accessToken,\n\t\t\t\trefreshToken: tokens.refreshToken,\n\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\tscope: tokens.scopes?.join(\",\") || account.scope,\n\t\t\t\tidToken: tokens.idToken || account.idToken,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t\taccountId: account.accountId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to refresh access token\",\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t},\n);\n\nconst accountInfoQuerySchema = z.optional(\n\tz.object({\n\t\taccountId: z\n\t\t\t.string()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"The provider given account id for which to get the account info\",\n\t\t\t})\n\t\t\t.optional(),\n\t}),\n);\n\nexport const accountInfo = createAuthEndpoint(\n\t\"/account-info\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Get the account info provided by the provider\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\temail: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\timage: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\temailVerified: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: [\"id\", \"emailVerified\"],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\tadditionalProperties: true,\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\trequired: [\"user\", \"data\"],\n\t\t\t\t\t\t\t\t\tadditionalProperties: false,\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\tquery: accountInfoQuerySchema,\n\t},\n\tasync (ctx) => {\n\t\tconst providedAccountId = ctx.query?.accountId;\n\t\tlet account: Account | undefined = undefined;\n\t\tif (!providedAccountId) {\n\t\t\tif (ctx.context.options.account?.storeAccountCookie) {\n\t\t\t\tconst accountData = await getAccountCookie(ctx);\n\t\t\t\tif (accountData) {\n\t\t\t\t\taccount = accountData;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst accountData =\n\t\t\t\tawait ctx.context.internalAdapter.findAccount(providedAccountId);\n\t\t\tif (accountData) {\n\t\t\t\taccount = accountData;\n\t\t\t}\n\t\t}\n\n\t\tif (!account || account.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === account.providerId,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: `Provider account provider is ${account.providerId} but it is not configured`,\n\t\t\t});\n\t\t}\n\t\tconst tokens = await getAccessToken({\n\t\t\t...ctx,\n\t\t\tmethod: \"POST\",\n\t\t\tbody: {\n\t\t\t\taccountId: account.id,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t},\n\t\t\treturnHeaders: false,\n\t\t\treturnStatus: false,\n\t\t});\n\t\tif (!tokens.accessToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Access token not found\",\n\t\t\t});\n\t\t}\n\t\tconst info = await provider.getUserInfo({\n\t\t\t...tokens,\n\t\t\taccessToken: tokens.accessToken as string,\n\t\t});\n\t\treturn ctx.json(info);\n\t},\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"account.mjs","names":["e: any","account: Account | undefined","newTokens: OAuth2Tokens | null","refreshToken","updatedAccount: Record<string, any> | null","refreshToken: string | null | undefined","tokens: OAuth2Tokens"],"sources":["../../../src/api/routes/account.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport type { Account } from \"@better-auth/core/db\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport type { OAuth2Tokens } from \"@better-auth/core/oauth2\";\nimport { SocialProviderListEnum } from \"@better-auth/core/social-providers\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport {\n\tgetAccountCookie,\n\tsetAccountCookie,\n} from \"../../cookies/session-store\";\nimport { parseAccountOutput } from \"../../db/schema\";\nimport { generateState } from \"../../oauth2/state\";\nimport { decryptOAuthToken, setTokenUtil } from \"../../oauth2/utils\";\nimport {\n\tfreshSessionMiddleware,\n\tgetSessionFromCtx,\n\tsessionMiddleware,\n} from \"./session\";\n\nexport const listUserAccounts = createAuthEndpoint(\n\t\"/list-accounts\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"listUserAccounts\",\n\t\t\t\tdescription: \"List all accounts linked to the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: {\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\tid: {\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},\n\t\t\t\t\t\t\t\t\t\t\tproviderId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tcreatedAt: {\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\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tupdatedAt: {\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\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\taccountId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tuserId: {\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},\n\t\t\t\t\t\t\t\t\t\t\tscopes: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\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\t},\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: [\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"providerId\",\n\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"accountId\",\n\t\t\t\t\t\t\t\t\t\t\t\"userId\",\n\t\t\t\t\t\t\t\t\t\t\t\"scopes\",\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},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\t\tconst accounts = await c.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\treturn c.json(\n\t\t\taccounts.map((a) => {\n\t\t\t\tconst { scope, ...parsed } = parseAccountOutput(c.context.options, a);\n\t\t\t\treturn {\n\t\t\t\t\t...parsed,\n\t\t\t\t\tscopes: scope?.split(\",\") || [],\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t},\n);\n\nexport const linkSocialAccount = createAuthEndpoint(\n\t\"/link-social\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * Callback URL to redirect to after the user has signed in.\n\t\t\t */\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to redirect to after the user has signed in\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * OAuth2 provider to use\n\t\t\t */\n\t\t\tprovider: SocialProviderListEnum,\n\t\t\t/**\n\t\t\t * ID Token for direct authentication without redirect\n\t\t\t */\n\t\t\tidToken: z\n\t\t\t\t.object({\n\t\t\t\t\ttoken: z.string(),\n\t\t\t\t\tnonce: z.string().optional(),\n\t\t\t\t\taccessToken: z.string().optional(),\n\t\t\t\t\trefreshToken: z.string().optional(),\n\t\t\t\t\tscopes: z.array(z.string()).optional(),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Whether to allow sign up for new users\n\t\t\t */\n\t\t\trequestSignUp: z.boolean().optional(),\n\t\t\t/**\n\t\t\t * Additional scopes to request when linking the account.\n\t\t\t * This is useful for requesting additional permissions when\n\t\t\t * linking a social account compared to the initial authentication.\n\t\t\t */\n\t\t\tscopes: z\n\t\t\t\t.array(z.string())\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Additional scopes to request from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * The URL to redirect to if there is an error during the link process.\n\t\t\t */\n\t\t\terrorCallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The URL to redirect to if there is an error during the link process\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Disable automatic redirection to the provider\n\t\t\t *\n\t\t\t * This is useful if you want to handle the redirection\n\t\t\t * yourself like in a popup or a different tab.\n\t\t\t */\n\t\t\tdisableRedirect: z\n\t\t\t\t.boolean()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Disable automatic redirection to the provider. Useful for handling the redirection yourself\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Any additional data to pass through the oauth flow.\n\t\t\t */\n\t\t\tadditionalData: z.record(z.string(), z.any()).optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Link a social account to the user\",\n\t\t\t\toperationId: \"linkSocialAccount\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"The authorization URL to redirect the user to\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the user should be redirected to the authorization URL\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\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\trequired: [\"redirect\"],\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},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.body.provider,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t{\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t});\n\t\t}\n\n\t\t// Handle ID Token flow if provided\n\t\tif (c.body.idToken) {\n\t\t\tif (!provider.verifyIdToken) {\n\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\"Provider does not support id token verification\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { token, nonce } = c.body.idToken;\n\t\t\tconst valid = await provider.verifyIdToken(token, nonce);\n\t\t\tif (!valid) {\n\t\t\t\tc.context.logger.error(\"Invalid id token\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst linkingUserInfo = await provider.getUserInfo({\n\t\t\t\tidToken: token,\n\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t});\n\n\t\t\tif (!linkingUserInfo || !linkingUserInfo?.user) {\n\t\t\t\tc.context.logger.error(\"Failed to get user info\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst linkingUserId = String(linkingUserInfo.user.id);\n\n\t\t\tif (!linkingUserInfo.user.email) {\n\t\t\t\tc.context.logger.error(\"User email not found\", {\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t});\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst existingAccounts = await c.context.internalAdapter.findAccounts(\n\t\t\t\tsession.user.id,\n\t\t\t);\n\n\t\t\tconst hasBeenLinked = existingAccounts.find(\n\t\t\t\t(a) => a.providerId === provider.id && a.accountId === linkingUserId,\n\t\t\t);\n\n\t\t\tif (hasBeenLinked) {\n\t\t\t\treturn c.json({\n\t\t\t\t\turl: \"\", // this is for type inference\n\t\t\t\t\tstatus: true,\n\t\t\t\t\tredirect: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\n\t\t\tconst isTrustedProvider = trustedProviders?.includes(provider.id);\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !linkingUserInfo.user.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Account not linked - linking not allowed\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tlinkingUserInfo.user.email?.toLowerCase() !==\n\t\t\t\t\tsession.user.email.toLowerCase() &&\n\t\t\t\tc.context.options.account?.accountLinking?.allowDifferentEmails !== true\n\t\t\t) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Account not linked - different emails not allowed\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait c.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\taccountId: linkingUserId,\n\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\tidToken: token,\n\t\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t\t\tscope: c.body.idToken.scopes?.join(\",\"),\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tthrow new APIError(\"EXPECTATION_FAILED\", {\n\t\t\t\t\tmessage: \"Account not linked - unable to create account\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tc.context.options.account?.accountLinking?.updateUserInfoOnLink === true\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\tawait c.context.internalAdapter.updateUser(session.user.id, {\n\t\t\t\t\t\tname: linkingUserInfo.user?.name,\n\t\t\t\t\t\timage: linkingUserInfo.user?.image,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tconsole.warn(\"Could not update user - \" + e.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\turl: \"\", // this is for type inference\n\t\t\t\tstatus: true,\n\t\t\t\tredirect: false,\n\t\t\t});\n\t\t}\n\n\t\t// Handle OAuth flow\n\t\tconst state = await generateState(\n\t\t\tc,\n\t\t\t{\n\t\t\t\tuserId: session.user.id,\n\t\t\t\temail: session.user.email,\n\t\t\t},\n\t\t\tc.body.additionalData,\n\t\t);\n\n\t\tconst url = await provider.createAuthorizationURL({\n\t\t\tstate: state.state,\n\t\t\tcodeVerifier: state.codeVerifier,\n\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\tscopes: c.body.scopes,\n\t\t});\n\n\t\tif (!c.body.disableRedirect) {\n\t\t\tc.setHeader(\"Location\", url.toString());\n\t\t}\n\n\t\treturn c.json({\n\t\t\turl: url.toString(),\n\t\t\tredirect: !c.body.disableRedirect,\n\t\t});\n\t},\n);\nexport const unlinkAccount = createAuthEndpoint(\n\t\"/unlink-account\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string(),\n\t\t\taccountId: z.string().optional(),\n\t\t}),\n\t\tuse: [freshSessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Unlink an account\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\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},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId } = ctx.body;\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tctx.context.session.user.id,\n\t\t);\n\t\tif (\n\t\t\taccounts.length === 1 &&\n\t\t\t!ctx.context.options.account?.accountLinking?.allowUnlinkingAll\n\t\t) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_UNLINK_LAST_ACCOUNT,\n\t\t\t});\n\t\t}\n\t\tconst accountExist = accounts.find((account) =>\n\t\t\taccountId\n\t\t\t\t? account.accountId === accountId && account.providerId === providerId\n\t\t\t\t: account.providerId === providerId,\n\t\t);\n\t\tif (!accountExist) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.ACCOUNT_NOT_FOUND,\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteAccount(accountExist.id);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const getAccessToken = createAuthEndpoint(\n\t\"/get-access-token\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string().meta({\n\t\t\t\tdescription: \"The provider ID for the OAuth provider\",\n\t\t\t}),\n\t\t\taccountId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The account ID associated with the refresh token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tuserId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The user ID associated with the account\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Get a valid access token, doing a refresh if needed\",\n\t\t\t\tresponses: {\n\t\t\t\t\t200: {\n\t\t\t\t\t\tdescription: \"A Valid access token\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttokenType: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tidToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\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\t400: {\n\t\t\t\t\t\tdescription: \"Invalid refresh token or provider configuration\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId, userId } = ctx.body || {};\n\t\tconst req = ctx.request;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (req && !session) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst resolvedUserId = session?.user?.id || userId;\n\t\tif (!resolvedUserId) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tif (!ctx.context.socialProviders.find((p) => p.id === providerId)) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} is not supported.`,\n\t\t\t});\n\t\t}\n\t\tconst accountData = await getAccountCookie(ctx);\n\t\tlet account: Account | undefined = undefined;\n\t\tif (\n\t\t\taccountData &&\n\t\t\tproviderId === accountData.providerId &&\n\t\t\t(!accountId || accountData.id === accountId)\n\t\t) {\n\t\t\taccount = accountData;\n\t\t} else {\n\t\t\tconst accounts =\n\t\t\t\tawait ctx.context.internalAdapter.findAccounts(resolvedUserId);\n\t\t\taccount = accounts.find((acc) =>\n\t\t\t\taccountId\n\t\t\t\t\t? acc.id === accountId && acc.providerId === providerId\n\t\t\t\t\t: acc.providerId === providerId,\n\t\t\t);\n\t\t}\n\n\t\tif (!account) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === providerId,\n\t\t);\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} not found.`,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tlet newTokens: OAuth2Tokens | null = null;\n\t\t\tconst accessTokenExpired =\n\t\t\t\taccount.accessTokenExpiresAt &&\n\t\t\t\tnew Date(account.accessTokenExpiresAt).getTime() - Date.now() < 5_000;\n\t\t\tif (\n\t\t\t\taccount.refreshToken &&\n\t\t\t\taccessTokenExpired &&\n\t\t\t\tprovider.refreshAccessToken\n\t\t\t) {\n\t\t\t\tconst refreshToken = await decryptOAuthToken(\n\t\t\t\t\taccount.refreshToken,\n\t\t\t\t\tctx.context,\n\t\t\t\t);\n\t\t\t\tnewTokens = await provider.refreshAccessToken(refreshToken);\n\t\t\t\tconst updatedData = {\n\t\t\t\t\taccessToken: await setTokenUtil(newTokens.accessToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: newTokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshToken: await setTokenUtil(newTokens.refreshToken, ctx.context),\n\t\t\t\t\trefreshTokenExpiresAt: newTokens.refreshTokenExpiresAt,\n\t\t\t\t};\n\t\t\t\tlet updatedAccount: Record<string, any> | null = null;\n\t\t\t\tif (account.id) {\n\t\t\t\t\tupdatedAccount = await ctx.context.internalAdapter.updateAccount(\n\t\t\t\t\t\taccount.id,\n\t\t\t\t\t\tupdatedData,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (ctx.context.options.account?.storeAccountCookie) {\n\t\t\t\t\tawait setAccountCookie(ctx, {\n\t\t\t\t\t\t...account,\n\t\t\t\t\t\t...(updatedAccount ?? updatedData),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst accessTokenExpiresAt = (() => {\n\t\t\t\tif (newTokens?.accessTokenExpiresAt) {\n\t\t\t\t\tif (typeof newTokens.accessTokenExpiresAt === \"string\") {\n\t\t\t\t\t\treturn new Date(newTokens.accessTokenExpiresAt);\n\t\t\t\t\t}\n\t\t\t\t\treturn newTokens.accessTokenExpiresAt;\n\t\t\t\t}\n\t\t\t\tif (account.accessTokenExpiresAt) {\n\t\t\t\t\tif (typeof account.accessTokenExpiresAt === \"string\") {\n\t\t\t\t\t\treturn new Date(account.accessTokenExpiresAt);\n\t\t\t\t\t}\n\t\t\t\t\treturn account.accessTokenExpiresAt;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})();\n\n\t\t\tconst tokens = {\n\t\t\t\taccessToken:\n\t\t\t\t\tnewTokens?.accessToken ??\n\t\t\t\t\t(await decryptOAuthToken(account.accessToken ?? \"\", ctx.context)),\n\t\t\t\taccessTokenExpiresAt,\n\t\t\t\tscopes: account.scope?.split(\",\") ?? [],\n\t\t\t\tidToken: newTokens?.idToken ?? account.idToken ?? undefined,\n\t\t\t};\n\t\t\treturn ctx.json(tokens);\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to get a valid access token\",\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t},\n);\n\nexport const refreshToken = createAuthEndpoint(\n\t\"/refresh-token\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tproviderId: z.string().meta({\n\t\t\t\tdescription: \"The provider ID for the OAuth provider\",\n\t\t\t}),\n\t\t\taccountId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The account ID associated with the refresh token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tuserId: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The user ID associated with the account\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Refresh the access token using a refresh token\",\n\t\t\t\tresponses: {\n\t\t\t\t\t200: {\n\t\t\t\t\t\tdescription: \"Access token refreshed successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttokenType: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tidToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trefreshToken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\taccessTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trefreshTokenExpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\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\t400: {\n\t\t\t\t\t\tdescription: \"Invalid refresh token or provider configuration\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst { providerId, accountId, userId } = ctx.body;\n\t\tconst req = ctx.request;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (req && !session) {\n\t\t\tthrow ctx.error(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst resolvedUserId = session?.user?.id || userId;\n\t\tif (!resolvedUserId) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Either userId or session is required`,\n\t\t\t});\n\t\t}\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === providerId,\n\t\t);\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} not found.`,\n\t\t\t});\n\t\t}\n\t\tif (!provider.refreshAccessToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `Provider ${providerId} does not support token refreshing.`,\n\t\t\t});\n\t\t}\n\n\t\t// Try to read refresh token from cookie first\n\t\tlet account: Account | undefined = undefined;\n\t\tconst accountData = await getAccountCookie(ctx);\n\t\tif (\n\t\t\taccountData &&\n\t\t\t(!providerId || providerId === accountData?.providerId)\n\t\t) {\n\t\t\taccount = accountData;\n\t\t} else {\n\t\t\tconst accounts =\n\t\t\t\tawait ctx.context.internalAdapter.findAccounts(resolvedUserId);\n\t\t\taccount = accounts.find((acc) =>\n\t\t\t\taccountId\n\t\t\t\t\t? acc.id === accountId && acc.providerId === providerId\n\t\t\t\t\t: acc.providerId === providerId,\n\t\t\t);\n\t\t}\n\n\t\tif (!account) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\n\t\tlet refreshToken: string | null | undefined = undefined;\n\t\tif (accountData && providerId === accountData.providerId) {\n\t\t\trefreshToken = accountData.refreshToken ?? undefined;\n\t\t} else {\n\t\t\trefreshToken = account.refreshToken ?? undefined;\n\t\t}\n\n\t\tif (!refreshToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Refresh token not found\",\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst decryptedRefreshToken = await decryptOAuthToken(\n\t\t\t\trefreshToken,\n\t\t\t\tctx.context,\n\t\t\t);\n\t\t\tconst tokens: OAuth2Tokens = await provider.refreshAccessToken(\n\t\t\t\tdecryptedRefreshToken,\n\t\t\t);\n\n\t\t\tif (account.id) {\n\t\t\t\tconst updateData = {\n\t\t\t\t\t...(account || {}),\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\") || account.scope,\n\t\t\t\t\tidToken: tokens.idToken || account.idToken,\n\t\t\t\t};\n\t\t\t\tawait ctx.context.internalAdapter.updateAccount(account.id, updateData);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\taccountData &&\n\t\t\t\tproviderId === accountData.providerId &&\n\t\t\t\tctx.context.options.account?.storeAccountCookie\n\t\t\t) {\n\t\t\t\tconst updateData = {\n\t\t\t\t\t...accountData,\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\") || accountData.scope,\n\t\t\t\t\tidToken: tokens.idToken || accountData.idToken,\n\t\t\t\t};\n\t\t\t\tawait setAccountCookie(ctx, updateData);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\taccessToken: tokens.accessToken,\n\t\t\t\trefreshToken: tokens.refreshToken,\n\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\tscope: tokens.scopes?.join(\",\") || account.scope,\n\t\t\t\tidToken: tokens.idToken || account.idToken,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t\taccountId: account.accountId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to refresh access token\",\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t},\n);\n\nconst accountInfoQuerySchema = z.optional(\n\tz.object({\n\t\taccountId: z\n\t\t\t.string()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"The provider given account id for which to get the account info\",\n\t\t\t})\n\t\t\t.optional(),\n\t}),\n);\n\nexport const accountInfo = createAuthEndpoint(\n\t\"/account-info\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Get the account info provided by the provider\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\temail: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\timage: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t\temailVerified: {\n\t\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\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: [\"id\", \"emailVerified\"],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\tadditionalProperties: true,\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\trequired: [\"user\", \"data\"],\n\t\t\t\t\t\t\t\t\tadditionalProperties: false,\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\tquery: accountInfoQuerySchema,\n\t},\n\tasync (ctx) => {\n\t\tconst providedAccountId = ctx.query?.accountId;\n\t\tlet account: Account | undefined = undefined;\n\t\tif (!providedAccountId) {\n\t\t\tif (ctx.context.options.account?.storeAccountCookie) {\n\t\t\t\tconst accountData = await getAccountCookie(ctx);\n\t\t\t\tif (accountData) {\n\t\t\t\t\taccount = accountData;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst accountData =\n\t\t\t\tawait ctx.context.internalAdapter.findAccount(providedAccountId);\n\t\t\tif (accountData) {\n\t\t\t\taccount = accountData;\n\t\t\t}\n\t\t}\n\n\t\tif (!account || account.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Account not found\",\n\t\t\t});\n\t\t}\n\n\t\tconst provider = ctx.context.socialProviders.find(\n\t\t\t(p) => p.id === account.providerId,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: `Provider account provider is ${account.providerId} but it is not configured`,\n\t\t\t});\n\t\t}\n\t\tconst tokens = await getAccessToken({\n\t\t\t...ctx,\n\t\t\tmethod: \"POST\",\n\t\t\tbody: {\n\t\t\t\taccountId: account.id,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t},\n\t\t\treturnHeaders: false,\n\t\t\treturnStatus: false,\n\t\t});\n\t\tif (!tokens.accessToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Access token not found\",\n\t\t\t});\n\t\t}\n\t\tconst info = await provider.getUserInfo({\n\t\t\t...tokens,\n\t\t\taccessToken: tokens.accessToken as string,\n\t\t});\n\t\treturn ctx.json(info);\n\t},\n);\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as better_call833 from "better-call";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/api/routes/callback.d.ts
|
|
5
|
-
declare const callbackOAuth:
|
|
5
|
+
declare const callbackOAuth: better_call833.StrictEndpoint<"/callback/:id", {
|
|
6
6
|
method: ("GET" | "POST")[];
|
|
7
7
|
operationId: string;
|
|
8
8
|
body: z.ZodOptional<z.ZodObject<{
|
|
@@ -103,7 +103,7 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
103
103
|
c.context.logger.error("Unable to link account - untrusted provider");
|
|
104
104
|
return redirectOnError("unable_to_link_account");
|
|
105
105
|
}
|
|
106
|
-
if (userInfo.email !== link.email && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) return redirectOnError("email_doesn't_match");
|
|
106
|
+
if (userInfo.email?.toLowerCase() !== link.email.toLowerCase() && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) return redirectOnError("email_doesn't_match");
|
|
107
107
|
const existingAccount = await c.context.internalAdapter.findAccount(String(userInfo.id));
|
|
108
108
|
if (existingAccount) {
|
|
109
109
|
if (existingAccount.userId.toString() !== link.userId.toString()) return redirectOnError("account_already_linked_to_different_user");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callback.mjs","names":["queryOrBody: z.infer<typeof schema>","tokens: OAuth2Tokens | null","toRedirectTo: string","toRedirectTo"],"sources":["../../../src/api/routes/callback.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport type { OAuth2Tokens } from \"@better-auth/core/oauth2\";\nimport { safeJSONParse } from \"@better-auth/core/utils\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport { parseState } from \"../../oauth2/state\";\nimport { setTokenUtil } from \"../../oauth2/utils\";\nimport { HIDE_METADATA } from \"../../utils/hide-metadata\";\n\nconst schema = z.object({\n\tcode: z.string().optional(),\n\terror: z.string().optional(),\n\tdevice_id: z.string().optional(),\n\terror_description: z.string().optional(),\n\tstate: z.string().optional(),\n\tuser: z.string().optional(),\n});\n\nexport const callbackOAuth = createAuthEndpoint(\n\t\"/callback/:id\",\n\t{\n\t\tmethod: [\"GET\", \"POST\"],\n\t\toperationId: \"handleOAuthCallback\",\n\t\tbody: schema.optional(),\n\t\tquery: schema.optional(),\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: [\n\t\t\t\t\"application/x-www-form-urlencoded\",\n\t\t\t\t\"application/json\",\n\t\t\t],\n\t\t},\n\t},\n\tasync (c) => {\n\t\tlet queryOrBody: z.infer<typeof schema>;\n\t\tconst defaultErrorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\n\t\t// Handle POST requests by redirecting to GET to ensure cookies are sent\n\t\tif (c.method === \"POST\") {\n\t\t\tconst postData = c.body ? schema.parse(c.body) : {};\n\t\t\tconst queryData = c.query ? schema.parse(c.query) : {};\n\n\t\t\tconst mergedData = schema.parse({ ...postData, ...queryData });\n\t\t\tconst params = new URLSearchParams();\n\n\t\t\tfor (const [key, value] of Object.entries(mergedData)) {\n\t\t\t\tif (value !== undefined && value !== null) {\n\t\t\t\t\tparams.set(key, String(value));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst redirectURL = `${c.context.baseURL}/callback/${c.params.id}?${params.toString()}`;\n\t\t\tthrow c.redirect(redirectURL);\n\t\t}\n\n\t\ttry {\n\t\t\tif (c.method === \"GET\") {\n\t\t\t\tqueryOrBody = schema.parse(c.query);\n\t\t\t} else if (c.method === \"POST\") {\n\t\t\t\tqueryOrBody = schema.parse(c.body);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Unsupported method\");\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(\"INVALID_CALLBACK_REQUEST\", e);\n\t\t\tthrow c.redirect(`${defaultErrorURL}?error=invalid_callback_request`);\n\t\t}\n\n\t\tconst {\n\t\t\tcode,\n\t\t\terror,\n\t\t\tstate,\n\t\t\terror_description,\n\t\t\tdevice_id,\n\t\t\tuser: userData,\n\t\t} = queryOrBody;\n\n\t\tif (!state) {\n\t\t\tc.context.logger.error(\"State not found\", error);\n\t\t\tconst sep = defaultErrorURL.includes(\"?\") ? \"&\" : \"?\";\n\t\t\tconst url = `${defaultErrorURL}${sep}state=state_not_found`;\n\t\t\tthrow c.redirect(url);\n\t\t}\n\n\t\tconst {\n\t\t\tcodeVerifier,\n\t\t\tcallbackURL,\n\t\t\tlink,\n\t\t\terrorURL,\n\t\t\tnewUserURL,\n\t\t\trequestSignUp,\n\t\t} = await parseState(c);\n\n\t\tfunction redirectOnError(error: string, description?: string | undefined) {\n\t\t\tconst baseURL = errorURL ?? defaultErrorURL;\n\n\t\t\tconst params = new URLSearchParams({ error });\n\t\t\tif (description) params.set(\"error_description\", description);\n\n\t\t\tconst sep = baseURL.includes(\"?\") ? \"&\" : \"?\";\n\t\t\tconst url = `${baseURL}${sep}${params.toString()}`;\n\n\t\t\tthrow c.redirect(url);\n\t\t}\n\n\t\tif (error) {\n\t\t\tredirectOnError(error, error_description);\n\t\t}\n\n\t\tif (!code) {\n\t\t\tc.context.logger.error(\"Code not found\");\n\t\t\tthrow redirectOnError(\"no_code\");\n\t\t}\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.params.id,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Oauth provider with id\",\n\t\t\t\tc.params.id,\n\t\t\t\t\"not found\",\n\t\t\t);\n\t\t\tthrow redirectOnError(\"oauth_provider_not_found\");\n\t\t}\n\n\t\tlet tokens: OAuth2Tokens | null;\n\t\ttry {\n\t\t\ttokens = await provider.validateAuthorizationCode({\n\t\t\t\tcode: code,\n\t\t\t\tcodeVerifier,\n\t\t\t\tdeviceId: device_id,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(\"\", e);\n\t\t\tthrow redirectOnError(\"invalid_code\");\n\t\t}\n\t\tif (!tokens) {\n\t\t\tthrow redirectOnError(\"invalid_code\");\n\t\t}\n\t\tconst parsedUserData = userData\n\t\t\t? safeJSONParse<{\n\t\t\t\t\tname?: {\n\t\t\t\t\t\tfirstName?: string;\n\t\t\t\t\t\tlastName?: string;\n\t\t\t\t\t};\n\t\t\t\t\temail?: string;\n\t\t\t\t}>(userData)\n\t\t\t: null;\n\n\t\tconst userInfo = await provider\n\t\t\t.getUserInfo({\n\t\t\t\t...tokens,\n\t\t\t\t/**\n\t\t\t\t * The user object from the provider\n\t\t\t\t * This is only available for some providers like Apple\n\t\t\t\t */\n\t\t\t\tuser: parsedUserData ?? undefined,\n\t\t\t})\n\t\t\t.then((res) => res?.user);\n\n\t\tif (!userInfo) {\n\t\t\tc.context.logger.error(\"Unable to get user info\");\n\t\t\treturn redirectOnError(\"unable_to_get_user_info\");\n\t\t}\n\n\t\tif (!callbackURL) {\n\t\t\tc.context.logger.error(\"No callback URL found\");\n\t\t\tthrow redirectOnError(\"no_callback_url\");\n\t\t}\n\n\t\tif (link) {\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\tconst isTrustedProvider = trustedProviders?.includes(provider.id);\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !userInfo.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tc.context.logger.error(\"Unable to link account - untrusted provider\");\n\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.email !== link.email &&\n\t\t\t\tc.context.options.account?.accountLinking?.allowDifferentEmails !== true\n\t\t\t) {\n\t\t\t\treturn redirectOnError(\"email_doesn't_match\");\n\t\t\t}\n\n\t\t\tconst existingAccount = await c.context.internalAdapter.findAccount(\n\t\t\t\tString(userInfo.id),\n\t\t\t);\n\n\t\t\tif (existingAccount) {\n\t\t\t\tif (existingAccount.userId.toString() !== link.userId.toString()) {\n\t\t\t\t\treturn redirectOnError(\"account_already_linked_to_different_user\");\n\t\t\t\t}\n\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\tObject.entries({\n\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, c.context),\n\t\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, c.context),\n\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t);\n\t\t\t\tawait c.context.internalAdapter.updateAccount(\n\t\t\t\t\texistingAccount.id,\n\t\t\t\t\tupdateData,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst newAccount = await c.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: link.userId,\n\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\taccountId: String(userInfo.id),\n\t\t\t\t\t...tokens,\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, c.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, c.context),\n\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t});\n\t\t\t\tif (!newAccount) {\n\t\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet toRedirectTo: string;\n\t\t\ttry {\n\t\t\t\tconst url = callbackURL;\n\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t} catch {\n\t\t\t\ttoRedirectTo = callbackURL;\n\t\t\t}\n\t\t\tthrow c.redirect(toRedirectTo);\n\t\t}\n\n\t\tif (!userInfo.email) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider did not return email. This could be due to misconfiguration in the provider settings.\",\n\t\t\t);\n\t\t\treturn redirectOnError(\"email_not_found\");\n\t\t}\n\t\tconst accountData = {\n\t\t\tproviderId: provider.id,\n\t\t\taccountId: String(userInfo.id),\n\t\t\t...tokens,\n\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t};\n\t\tconst result = await handleOAuthUserInfo(c, {\n\t\t\tuserInfo: {\n\t\t\t\t...userInfo,\n\t\t\t\tid: String(userInfo.id),\n\t\t\t\temail: userInfo.email,\n\t\t\t\tname: userInfo.name || userInfo.email,\n\t\t\t},\n\t\t\taccount: accountData,\n\t\t\tcallbackURL,\n\t\t\tdisableSignUp:\n\t\t\t\t(provider.disableImplicitSignUp && !requestSignUp) ||\n\t\t\t\tprovider.options?.disableSignUp,\n\t\t\toverrideUserInfo: provider.options?.overrideUserInfoOnSignIn,\n\t\t});\n\t\tif (result.error) {\n\t\t\tc.context.logger.error(result.error.split(\" \").join(\"_\"));\n\t\t\treturn redirectOnError(result.error.split(\" \").join(\"_\"));\n\t\t}\n\t\tconst { session, user } = result.data!;\n\t\tawait setSessionCookie(c, {\n\t\t\tsession,\n\t\t\tuser,\n\t\t});\n\n\t\tlet toRedirectTo: string;\n\t\ttry {\n\t\t\tconst url = result.isRegister ? newUserURL || callbackURL : callbackURL;\n\t\t\ttoRedirectTo = url.toString();\n\t\t} catch {\n\t\t\ttoRedirectTo = result.isRegister\n\t\t\t\t? newUserURL || callbackURL\n\t\t\t\t: callbackURL;\n\t\t}\n\t\tthrow c.redirect(toRedirectTo);\n\t},\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"callback.mjs","names":["queryOrBody: z.infer<typeof schema>","tokens: OAuth2Tokens | null","toRedirectTo: string","toRedirectTo"],"sources":["../../../src/api/routes/callback.ts"],"sourcesContent":["import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport type { OAuth2Tokens } from \"@better-auth/core/oauth2\";\nimport { safeJSONParse } from \"@better-auth/core/utils\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport { parseState } from \"../../oauth2/state\";\nimport { setTokenUtil } from \"../../oauth2/utils\";\nimport { HIDE_METADATA } from \"../../utils/hide-metadata\";\n\nconst schema = z.object({\n\tcode: z.string().optional(),\n\terror: z.string().optional(),\n\tdevice_id: z.string().optional(),\n\terror_description: z.string().optional(),\n\tstate: z.string().optional(),\n\tuser: z.string().optional(),\n});\n\nexport const callbackOAuth = createAuthEndpoint(\n\t\"/callback/:id\",\n\t{\n\t\tmethod: [\"GET\", \"POST\"],\n\t\toperationId: \"handleOAuthCallback\",\n\t\tbody: schema.optional(),\n\t\tquery: schema.optional(),\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: [\n\t\t\t\t\"application/x-www-form-urlencoded\",\n\t\t\t\t\"application/json\",\n\t\t\t],\n\t\t},\n\t},\n\tasync (c) => {\n\t\tlet queryOrBody: z.infer<typeof schema>;\n\t\tconst defaultErrorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\n\t\t// Handle POST requests by redirecting to GET to ensure cookies are sent\n\t\tif (c.method === \"POST\") {\n\t\t\tconst postData = c.body ? schema.parse(c.body) : {};\n\t\t\tconst queryData = c.query ? schema.parse(c.query) : {};\n\n\t\t\tconst mergedData = schema.parse({ ...postData, ...queryData });\n\t\t\tconst params = new URLSearchParams();\n\n\t\t\tfor (const [key, value] of Object.entries(mergedData)) {\n\t\t\t\tif (value !== undefined && value !== null) {\n\t\t\t\t\tparams.set(key, String(value));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst redirectURL = `${c.context.baseURL}/callback/${c.params.id}?${params.toString()}`;\n\t\t\tthrow c.redirect(redirectURL);\n\t\t}\n\n\t\ttry {\n\t\t\tif (c.method === \"GET\") {\n\t\t\t\tqueryOrBody = schema.parse(c.query);\n\t\t\t} else if (c.method === \"POST\") {\n\t\t\t\tqueryOrBody = schema.parse(c.body);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Unsupported method\");\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(\"INVALID_CALLBACK_REQUEST\", e);\n\t\t\tthrow c.redirect(`${defaultErrorURL}?error=invalid_callback_request`);\n\t\t}\n\n\t\tconst {\n\t\t\tcode,\n\t\t\terror,\n\t\t\tstate,\n\t\t\terror_description,\n\t\t\tdevice_id,\n\t\t\tuser: userData,\n\t\t} = queryOrBody;\n\n\t\tif (!state) {\n\t\t\tc.context.logger.error(\"State not found\", error);\n\t\t\tconst sep = defaultErrorURL.includes(\"?\") ? \"&\" : \"?\";\n\t\t\tconst url = `${defaultErrorURL}${sep}state=state_not_found`;\n\t\t\tthrow c.redirect(url);\n\t\t}\n\n\t\tconst {\n\t\t\tcodeVerifier,\n\t\t\tcallbackURL,\n\t\t\tlink,\n\t\t\terrorURL,\n\t\t\tnewUserURL,\n\t\t\trequestSignUp,\n\t\t} = await parseState(c);\n\n\t\tfunction redirectOnError(error: string, description?: string | undefined) {\n\t\t\tconst baseURL = errorURL ?? defaultErrorURL;\n\n\t\t\tconst params = new URLSearchParams({ error });\n\t\t\tif (description) params.set(\"error_description\", description);\n\n\t\t\tconst sep = baseURL.includes(\"?\") ? \"&\" : \"?\";\n\t\t\tconst url = `${baseURL}${sep}${params.toString()}`;\n\n\t\t\tthrow c.redirect(url);\n\t\t}\n\n\t\tif (error) {\n\t\t\tredirectOnError(error, error_description);\n\t\t}\n\n\t\tif (!code) {\n\t\t\tc.context.logger.error(\"Code not found\");\n\t\t\tthrow redirectOnError(\"no_code\");\n\t\t}\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.params.id,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Oauth provider with id\",\n\t\t\t\tc.params.id,\n\t\t\t\t\"not found\",\n\t\t\t);\n\t\t\tthrow redirectOnError(\"oauth_provider_not_found\");\n\t\t}\n\n\t\tlet tokens: OAuth2Tokens | null;\n\t\ttry {\n\t\t\ttokens = await provider.validateAuthorizationCode({\n\t\t\t\tcode: code,\n\t\t\t\tcodeVerifier,\n\t\t\t\tdeviceId: device_id,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(\"\", e);\n\t\t\tthrow redirectOnError(\"invalid_code\");\n\t\t}\n\t\tif (!tokens) {\n\t\t\tthrow redirectOnError(\"invalid_code\");\n\t\t}\n\t\tconst parsedUserData = userData\n\t\t\t? safeJSONParse<{\n\t\t\t\t\tname?: {\n\t\t\t\t\t\tfirstName?: string;\n\t\t\t\t\t\tlastName?: string;\n\t\t\t\t\t};\n\t\t\t\t\temail?: string;\n\t\t\t\t}>(userData)\n\t\t\t: null;\n\n\t\tconst userInfo = await provider\n\t\t\t.getUserInfo({\n\t\t\t\t...tokens,\n\t\t\t\t/**\n\t\t\t\t * The user object from the provider\n\t\t\t\t * This is only available for some providers like Apple\n\t\t\t\t */\n\t\t\t\tuser: parsedUserData ?? undefined,\n\t\t\t})\n\t\t\t.then((res) => res?.user);\n\n\t\tif (!userInfo) {\n\t\t\tc.context.logger.error(\"Unable to get user info\");\n\t\t\treturn redirectOnError(\"unable_to_get_user_info\");\n\t\t}\n\n\t\tif (!callbackURL) {\n\t\t\tc.context.logger.error(\"No callback URL found\");\n\t\t\tthrow redirectOnError(\"no_callback_url\");\n\t\t}\n\n\t\tif (link) {\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\tconst isTrustedProvider = trustedProviders?.includes(provider.id);\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !userInfo.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tc.context.logger.error(\"Unable to link account - untrusted provider\");\n\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.email?.toLowerCase() !== link.email.toLowerCase() &&\n\t\t\t\tc.context.options.account?.accountLinking?.allowDifferentEmails !== true\n\t\t\t) {\n\t\t\t\treturn redirectOnError(\"email_doesn't_match\");\n\t\t\t}\n\n\t\t\tconst existingAccount = await c.context.internalAdapter.findAccount(\n\t\t\t\tString(userInfo.id),\n\t\t\t);\n\n\t\t\tif (existingAccount) {\n\t\t\t\tif (existingAccount.userId.toString() !== link.userId.toString()) {\n\t\t\t\t\treturn redirectOnError(\"account_already_linked_to_different_user\");\n\t\t\t\t}\n\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\tObject.entries({\n\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, c.context),\n\t\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, c.context),\n\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t);\n\t\t\t\tawait c.context.internalAdapter.updateAccount(\n\t\t\t\t\texistingAccount.id,\n\t\t\t\t\tupdateData,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst newAccount = await c.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: link.userId,\n\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\taccountId: String(userInfo.id),\n\t\t\t\t\t...tokens,\n\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, c.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(tokens.refreshToken, c.context),\n\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t});\n\t\t\t\tif (!newAccount) {\n\t\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet toRedirectTo: string;\n\t\t\ttry {\n\t\t\t\tconst url = callbackURL;\n\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t} catch {\n\t\t\t\ttoRedirectTo = callbackURL;\n\t\t\t}\n\t\t\tthrow c.redirect(toRedirectTo);\n\t\t}\n\n\t\tif (!userInfo.email) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider did not return email. This could be due to misconfiguration in the provider settings.\",\n\t\t\t);\n\t\t\treturn redirectOnError(\"email_not_found\");\n\t\t}\n\t\tconst accountData = {\n\t\t\tproviderId: provider.id,\n\t\t\taccountId: String(userInfo.id),\n\t\t\t...tokens,\n\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t};\n\t\tconst result = await handleOAuthUserInfo(c, {\n\t\t\tuserInfo: {\n\t\t\t\t...userInfo,\n\t\t\t\tid: String(userInfo.id),\n\t\t\t\temail: userInfo.email,\n\t\t\t\tname: userInfo.name || userInfo.email,\n\t\t\t},\n\t\t\taccount: accountData,\n\t\t\tcallbackURL,\n\t\t\tdisableSignUp:\n\t\t\t\t(provider.disableImplicitSignUp && !requestSignUp) ||\n\t\t\t\tprovider.options?.disableSignUp,\n\t\t\toverrideUserInfo: provider.options?.overrideUserInfoOnSignIn,\n\t\t});\n\t\tif (result.error) {\n\t\t\tc.context.logger.error(result.error.split(\" \").join(\"_\"));\n\t\t\treturn redirectOnError(result.error.split(\" \").join(\"_\"));\n\t\t}\n\t\tconst { session, user } = result.data!;\n\t\tawait setSessionCookie(c, {\n\t\t\tsession,\n\t\t\tuser,\n\t\t});\n\n\t\tlet toRedirectTo: string;\n\t\ttry {\n\t\t\tconst url = result.isRegister ? newUserURL || callbackURL : callbackURL;\n\t\t\ttoRedirectTo = url.toString();\n\t\t} catch {\n\t\t\ttoRedirectTo = result.isRegister\n\t\t\t\t? newUserURL || callbackURL\n\t\t\t\t: callbackURL;\n\t\t}\n\t\tthrow c.redirect(toRedirectTo);\n\t},\n);\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { User } from "../../types/models.mjs";
|
|
2
2
|
import "../../types/index.mjs";
|
|
3
3
|
import { GenericEndpointContext } from "@better-auth/core";
|
|
4
|
-
import * as
|
|
4
|
+
import * as better_call828 from "better-call";
|
|
5
5
|
import * as z from "zod";
|
|
6
6
|
|
|
7
7
|
//#region src/api/routes/email-verification.d.ts
|
|
@@ -22,7 +22,7 @@ extraPayload?: Record<string, any>): Promise<string>;
|
|
|
22
22
|
* A function to send a verification email to the user
|
|
23
23
|
*/
|
|
24
24
|
declare function sendVerificationEmailFn(ctx: GenericEndpointContext, user: User): Promise<void>;
|
|
25
|
-
declare const sendVerificationEmail:
|
|
25
|
+
declare const sendVerificationEmail: better_call828.StrictEndpoint<"/send-verification-email", {
|
|
26
26
|
method: "POST";
|
|
27
27
|
operationId: string;
|
|
28
28
|
body: z.ZodObject<{
|
|
@@ -97,14 +97,14 @@ declare const sendVerificationEmail: better_call763.StrictEndpoint<"/send-verifi
|
|
|
97
97
|
}, {
|
|
98
98
|
status: boolean;
|
|
99
99
|
}>;
|
|
100
|
-
declare const verifyEmail:
|
|
100
|
+
declare const verifyEmail: better_call828.StrictEndpoint<"/verify-email", {
|
|
101
101
|
method: "GET";
|
|
102
102
|
operationId: string;
|
|
103
103
|
query: z.ZodObject<{
|
|
104
104
|
token: z.ZodString;
|
|
105
105
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
106
106
|
}, z.core.$strip>;
|
|
107
|
-
use: ((inputContext:
|
|
107
|
+
use: ((inputContext: better_call828.MiddlewareInputContext<better_call828.MiddlewareOptions>) => Promise<void>)[];
|
|
108
108
|
metadata: {
|
|
109
109
|
openapi: {
|
|
110
110
|
description: string;
|
|
@@ -97,7 +97,7 @@ const sendVerificationEmail = createAuthEndpoint("/send-verification-email", {
|
|
|
97
97
|
const session = await getSessionFromCtx(ctx);
|
|
98
98
|
if (!session) {
|
|
99
99
|
const user = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
100
|
-
if (!user) {
|
|
100
|
+
if (!user || user.user.emailVerified) {
|
|
101
101
|
await createEmailVerificationToken(ctx.context.secret, email, void 0, ctx.context.options.emailVerification?.expiresIn);
|
|
102
102
|
return ctx.json({ status: true });
|
|
103
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-verification.mjs","names":["jwt: JWTVerifyResult<JWTPayload>","updatedUser"],"sources":["../../../src/api/routes/email-verification.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { APIError } from \"better-call\";\nimport type { JWTPayload, JWTVerifyResult } from \"jose\";\nimport { jwtVerify } from \"jose\";\nimport { JWTExpired } from \"jose/errors\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { signJWT } from \"../../crypto/jwt\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport type { User } from \"../../types\";\nimport { originCheck } from \"../middlewares\";\nimport { getSessionFromCtx } from \"./session\";\n\nexport async function createEmailVerificationToken(\n\tsecret: string,\n\temail: string,\n\t/**\n\t * The email to update from\n\t */\n\tupdateTo?: string | undefined,\n\t/**\n\t * The time in seconds for the token to expire\n\t */\n\texpiresIn: number = 3600,\n\t/**\n\t * Extra payload to include in the token\n\t */\n\textraPayload?: Record<string, any>,\n) {\n\tconst token = await signJWT(\n\t\t{\n\t\t\temail: email.toLowerCase(),\n\t\t\tupdateTo,\n\t\t\t...extraPayload,\n\t\t},\n\t\tsecret,\n\t\texpiresIn,\n\t);\n\treturn token;\n}\n\n/**\n * A function to send a verification email to the user\n */\nexport async function sendVerificationEmailFn(\n\tctx: GenericEndpointContext,\n\tuser: User,\n) {\n\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t});\n\t}\n\tconst token = await createEmailVerificationToken(\n\t\tctx.context.secret,\n\t\tuser.email,\n\t\tundefined,\n\t\tctx.context.options.emailVerification?.expiresIn,\n\t);\n\tconst callbackURL = ctx.body.callbackURL\n\t\t? encodeURIComponent(ctx.body.callbackURL)\n\t\t: encodeURIComponent(\"/\");\n\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\tawait ctx.context.runInBackgroundOrAwait(\n\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t{\n\t\t\t\tuser: user,\n\t\t\t\turl,\n\t\t\t\ttoken,\n\t\t\t},\n\t\t\tctx.request,\n\t\t),\n\t);\n}\nexport const sendVerificationEmail = createAuthEndpoint(\n\t\"/send-verification-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\toperationId: \"sendVerificationEmail\",\n\t\tbody: z.object({\n\t\t\temail: z.email().meta({\n\t\t\t\tdescription: \"The email to send the verification email to\",\n\t\t\t}),\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to use for email verification callback\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"sendVerificationEmail\",\n\t\t\t\tdescription: \"Send a verification email to the user\",\n\t\t\t\trequestBody: {\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"The email to send the verification email to\",\n\t\t\t\t\t\t\t\t\t\texample: \"user@example.com\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tcallbackURL: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\"The URL to use for email verification callback\",\n\t\t\t\t\t\t\t\t\t\texample: \"https://example.com/callback\",\n\t\t\t\t\t\t\t\t\t\tnullable: true,\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\trequired: [\"email\"],\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\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the email was sent successfully\",\n\t\t\t\t\t\t\t\t\t\t\texample: true,\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\t\"400\": {\n\t\t\t\t\t\tdescription: \"Bad Request\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"Error message\",\n\t\t\t\t\t\t\t\t\t\t\texample: \"Verification email isn't enabled\",\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},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email } = ctx.body;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (!session) {\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user) {\n\t\t\t\tawait createEmailVerificationToken(\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t\temail,\n\t\t\t\t\tundefined,\n\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t);\n\t\t\t\t//we're returning true to avoid leaking information about the user\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tstatus: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait sendVerificationEmailFn(ctx, user.user);\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tif (session?.user.email !== email) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_MISMATCH,\n\t\t\t});\n\t\t}\n\t\tif (session?.user.emailVerified) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_ALREADY_VERIFIED,\n\t\t\t});\n\t\t}\n\t\tawait sendVerificationEmailFn(ctx, session.user);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const verifyEmail = createAuthEndpoint(\n\t\"/verify-email\",\n\t{\n\t\tmethod: \"GET\",\n\t\toperationId: \"verifyEmail\",\n\t\tquery: z.object({\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"The token to verify the email\",\n\t\t\t}),\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to redirect to after email verification\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tuse: [originCheck((ctx) => ctx.query.callbackURL)],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Verify the email of the user\",\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"token\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\tdescription: \"The token to verify the email\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"callbackURL\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\tdescription: \"The URL to redirect to after email verification\",\n\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\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},\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the email was verified successfully\",\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\trequired: [\"user\", \"status\"],\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},\n\tasync (ctx) => {\n\t\tfunction redirectOnError(error: string) {\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tif (ctx.query.callbackURL.includes(\"?\")) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}&error=${error}`);\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=${error}`);\n\t\t\t}\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: error,\n\t\t\t});\n\t\t}\n\t\tconst { token } = ctx.query;\n\t\tlet jwt: JWTVerifyResult<JWTPayload>;\n\t\ttry {\n\t\t\tjwt = await jwtVerify(\n\t\t\t\ttoken,\n\t\t\t\tnew TextEncoder().encode(ctx.context.secret),\n\t\t\t\t{\n\t\t\t\t\talgorithms: [\"HS256\"],\n\t\t\t\t},\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tif (e instanceof JWTExpired) {\n\t\t\t\treturn redirectOnError(\"token_expired\");\n\t\t\t}\n\t\t\treturn redirectOnError(\"invalid_token\");\n\t\t}\n\t\tconst schema = z.object({\n\t\t\temail: z.email(),\n\t\t\tupdateTo: z.string().optional(),\n\t\t\trequestType: z.string().optional(),\n\t\t});\n\t\tconst parsed = schema.parse(jwt.payload);\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tparsed.email,\n\t\t);\n\t\tif (!user) {\n\t\t\treturn redirectOnError(\"user_not_found\");\n\t\t}\n\t\tif (parsed.updateTo) {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (session && session.user.email !== parsed.email) {\n\t\t\t\treturn redirectOnError(\"unauthorized\");\n\t\t\t}\n\t\t\tswitch (parsed.requestType) {\n\t\t\t\t/**\n\t\t\t\t * User clicks confirmation -> sends verification to new email\n\t\t\t\t */\n\t\t\t\tcase \"change-email-confirmation\": {\n\t\t\t\t\tconst newToken = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tparsed.email,\n\t\t\t\t\t\tparsed.updateTo,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t\t{ requestType: \"change-email-verification\" },\n\t\t\t\t\t);\n\t\t\t\t\tconst updateCallbackURL = ctx.query.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.query.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${newToken}&callbackURL=${updateCallbackURL}`;\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: { ...user.user, email: parsed.updateTo },\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\ttoken: newToken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\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\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({ status: true });\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * User clicks verification -> updates email\n\t\t\t\t */\n\t\t\t\tcase \"change-email-verification\": {\n\t\t\t\t\tlet activeSession = session;\n\t\t\t\t\tif (!activeSession) {\n\t\t\t\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.user.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!newSession) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveSession = {\n\t\t\t\t\t\t\tsession: newSession,\n\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\t\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\t\t\t\tuser.user,\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst updatedUser =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t\t});\n\t\t\t\t\tif (ctx.context.options.emailVerification?.afterEmailVerification) {\n\t\t\t\t\t\tawait ctx.context.options.emailVerification.afterEmailVerification(\n\t\t\t\t\t\t\tupdatedUser,\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\t\tsession: activeSession.session,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...activeSession.user,\n\t\t\t\t\t\t\temail: parsed.updateTo,\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\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * Legacy flow\n\t\t\t\t *\n\t\t\t\t * - skips two-step verification\n\t\t\t\t * - updates email immediately\n\t\t\t\t */\n\t\t\t\tdefault: {\n\t\t\t\t\tlet activeSession = session;\n\t\t\t\t\tif (!activeSession) {\n\t\t\t\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.user.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!newSession) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveSession = {\n\t\t\t\t\t\t\tsession: newSession,\n\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tconst updatedUser =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t});\n\t\t\t\t\tconst newToken = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tparsed.updateTo,\n\t\t\t\t\t);\n\t\t\t\t\tconst updateCallbackURL = ctx.query.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.query.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: updatedUser,\n\t\t\t\t\t\t\t\t\turl: `${ctx.context.baseURL}/verify-email?token=${newToken}&callbackURL=${updateCallbackURL}`,\n\t\t\t\t\t\t\t\t\ttoken: newToken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\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\tawait setSessionCookie(ctx, {\n\t\t\t\t\t\tsession: activeSession.session,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...activeSession.user,\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (user.user.emailVerified) {\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t\tuser: null,\n\t\t\t});\n\t\t}\n\t\tif (ctx.context.options.emailVerification?.beforeEmailVerification) {\n\t\t\tawait ctx.context.options.emailVerification.beforeEmailVerification(\n\t\t\t\tuser.user,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t}\n\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\tuser.user,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t}\n\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\tparsed.email,\n\t\t\t{\n\t\t\t\temailVerified: true,\n\t\t\t},\n\t\t);\n\t\tif (ctx.context.options.emailVerification?.afterEmailVerification) {\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\t\t}\n\t\tif (ctx.context.options.emailVerification?.autoSignInAfterVerification) {\n\t\t\tconst currentSession = await getSessionFromCtx(ctx);\n\t\t\tif (!currentSession || currentSession.user.email !== parsed.email) {\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tuser.user.id,\n\t\t\t\t);\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...user.user,\n\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession: currentSession.session,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...currentSession.user,\n\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (ctx.query.callbackURL) {\n\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t\tuser: null,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"email-verification.mjs","names":["jwt: JWTVerifyResult<JWTPayload>","updatedUser"],"sources":["../../../src/api/routes/email-verification.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { APIError } from \"better-call\";\nimport type { JWTPayload, JWTVerifyResult } from \"jose\";\nimport { jwtVerify } from \"jose\";\nimport { JWTExpired } from \"jose/errors\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { signJWT } from \"../../crypto/jwt\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport type { User } from \"../../types\";\nimport { originCheck } from \"../middlewares\";\nimport { getSessionFromCtx } from \"./session\";\n\nexport async function createEmailVerificationToken(\n\tsecret: string,\n\temail: string,\n\t/**\n\t * The email to update from\n\t */\n\tupdateTo?: string | undefined,\n\t/**\n\t * The time in seconds for the token to expire\n\t */\n\texpiresIn: number = 3600,\n\t/**\n\t * Extra payload to include in the token\n\t */\n\textraPayload?: Record<string, any>,\n) {\n\tconst token = await signJWT(\n\t\t{\n\t\t\temail: email.toLowerCase(),\n\t\t\tupdateTo,\n\t\t\t...extraPayload,\n\t\t},\n\t\tsecret,\n\t\texpiresIn,\n\t);\n\treturn token;\n}\n\n/**\n * A function to send a verification email to the user\n */\nexport async function sendVerificationEmailFn(\n\tctx: GenericEndpointContext,\n\tuser: User,\n) {\n\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t});\n\t}\n\tconst token = await createEmailVerificationToken(\n\t\tctx.context.secret,\n\t\tuser.email,\n\t\tundefined,\n\t\tctx.context.options.emailVerification?.expiresIn,\n\t);\n\tconst callbackURL = ctx.body.callbackURL\n\t\t? encodeURIComponent(ctx.body.callbackURL)\n\t\t: encodeURIComponent(\"/\");\n\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\tawait ctx.context.runInBackgroundOrAwait(\n\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t{\n\t\t\t\tuser: user,\n\t\t\t\turl,\n\t\t\t\ttoken,\n\t\t\t},\n\t\t\tctx.request,\n\t\t),\n\t);\n}\nexport const sendVerificationEmail = createAuthEndpoint(\n\t\"/send-verification-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\toperationId: \"sendVerificationEmail\",\n\t\tbody: z.object({\n\t\t\temail: z.email().meta({\n\t\t\t\tdescription: \"The email to send the verification email to\",\n\t\t\t}),\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to use for email verification callback\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"sendVerificationEmail\",\n\t\t\t\tdescription: \"Send a verification email to the user\",\n\t\t\t\trequestBody: {\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"The email to send the verification email to\",\n\t\t\t\t\t\t\t\t\t\texample: \"user@example.com\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tcallbackURL: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\"The URL to use for email verification callback\",\n\t\t\t\t\t\t\t\t\t\texample: \"https://example.com/callback\",\n\t\t\t\t\t\t\t\t\t\tnullable: true,\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\trequired: [\"email\"],\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\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the email was sent successfully\",\n\t\t\t\t\t\t\t\t\t\t\texample: true,\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\t\"400\": {\n\t\t\t\t\t\tdescription: \"Bad Request\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"Error message\",\n\t\t\t\t\t\t\t\t\t\t\texample: \"Verification email isn't enabled\",\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},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email } = ctx.body;\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (!session) {\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (!user || user.user.emailVerified) {\n\t\t\t\tawait createEmailVerificationToken(\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t\temail,\n\t\t\t\t\tundefined,\n\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t);\n\t\t\t\t// We're returning true to avoid leaking information about the user\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tstatus: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait sendVerificationEmailFn(ctx, user.user);\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tif (session?.user.email !== email) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_MISMATCH,\n\t\t\t});\n\t\t}\n\t\tif (session?.user.emailVerified) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_ALREADY_VERIFIED,\n\t\t\t});\n\t\t}\n\t\tawait sendVerificationEmailFn(ctx, session.user);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const verifyEmail = createAuthEndpoint(\n\t\"/verify-email\",\n\t{\n\t\tmethod: \"GET\",\n\t\toperationId: \"verifyEmail\",\n\t\tquery: z.object({\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"The token to verify the email\",\n\t\t\t}),\n\t\t\tcallbackURL: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The URL to redirect to after email verification\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tuse: [originCheck((ctx) => ctx.query.callbackURL)],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Verify the email of the user\",\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"token\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\tdescription: \"The token to verify the email\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"callbackURL\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\tdescription: \"The URL to redirect to after email verification\",\n\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\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},\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the email was verified successfully\",\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\trequired: [\"user\", \"status\"],\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},\n\tasync (ctx) => {\n\t\tfunction redirectOnError(error: string) {\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tif (ctx.query.callbackURL.includes(\"?\")) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}&error=${error}`);\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=${error}`);\n\t\t\t}\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: error,\n\t\t\t});\n\t\t}\n\t\tconst { token } = ctx.query;\n\t\tlet jwt: JWTVerifyResult<JWTPayload>;\n\t\ttry {\n\t\t\tjwt = await jwtVerify(\n\t\t\t\ttoken,\n\t\t\t\tnew TextEncoder().encode(ctx.context.secret),\n\t\t\t\t{\n\t\t\t\t\talgorithms: [\"HS256\"],\n\t\t\t\t},\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tif (e instanceof JWTExpired) {\n\t\t\t\treturn redirectOnError(\"token_expired\");\n\t\t\t}\n\t\t\treturn redirectOnError(\"invalid_token\");\n\t\t}\n\t\tconst schema = z.object({\n\t\t\temail: z.email(),\n\t\t\tupdateTo: z.string().optional(),\n\t\t\trequestType: z.string().optional(),\n\t\t});\n\t\tconst parsed = schema.parse(jwt.payload);\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tparsed.email,\n\t\t);\n\t\tif (!user) {\n\t\t\treturn redirectOnError(\"user_not_found\");\n\t\t}\n\t\tif (parsed.updateTo) {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (session && session.user.email !== parsed.email) {\n\t\t\t\treturn redirectOnError(\"unauthorized\");\n\t\t\t}\n\t\t\tswitch (parsed.requestType) {\n\t\t\t\t/**\n\t\t\t\t * User clicks confirmation -> sends verification to new email\n\t\t\t\t */\n\t\t\t\tcase \"change-email-confirmation\": {\n\t\t\t\t\tconst newToken = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tparsed.email,\n\t\t\t\t\t\tparsed.updateTo,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t\t{ requestType: \"change-email-verification\" },\n\t\t\t\t\t);\n\t\t\t\t\tconst updateCallbackURL = ctx.query.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.query.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${newToken}&callbackURL=${updateCallbackURL}`;\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: { ...user.user, email: parsed.updateTo },\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\ttoken: newToken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\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\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({ status: true });\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * User clicks verification -> updates email\n\t\t\t\t */\n\t\t\t\tcase \"change-email-verification\": {\n\t\t\t\t\tlet activeSession = session;\n\t\t\t\t\tif (!activeSession) {\n\t\t\t\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.user.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!newSession) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveSession = {\n\t\t\t\t\t\t\tsession: newSession,\n\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\t\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\t\t\t\tuser.user,\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst updatedUser =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t\t});\n\t\t\t\t\tif (ctx.context.options.emailVerification?.afterEmailVerification) {\n\t\t\t\t\t\tawait ctx.context.options.emailVerification.afterEmailVerification(\n\t\t\t\t\t\t\tupdatedUser,\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\t\tsession: activeSession.session,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...activeSession.user,\n\t\t\t\t\t\t\temail: parsed.updateTo,\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\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * Legacy flow\n\t\t\t\t *\n\t\t\t\t * - skips two-step verification\n\t\t\t\t * - updates email immediately\n\t\t\t\t */\n\t\t\t\tdefault: {\n\t\t\t\t\tlet activeSession = session;\n\t\t\t\t\tif (!activeSession) {\n\t\t\t\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.user.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!newSession) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveSession = {\n\t\t\t\t\t\t\tsession: newSession,\n\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tconst updatedUser =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t});\n\t\t\t\t\tconst newToken = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tparsed.updateTo,\n\t\t\t\t\t);\n\t\t\t\t\tconst updateCallbackURL = ctx.query.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.query.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: updatedUser,\n\t\t\t\t\t\t\t\t\turl: `${ctx.context.baseURL}/verify-email?token=${newToken}&callbackURL=${updateCallbackURL}`,\n\t\t\t\t\t\t\t\t\ttoken: newToken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\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\tawait setSessionCookie(ctx, {\n\t\t\t\t\t\tsession: activeSession.session,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...activeSession.user,\n\t\t\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t\tuser: parseUserOutput(ctx.context.options, updatedUser),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (user.user.emailVerified) {\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t\tuser: null,\n\t\t\t});\n\t\t}\n\t\tif (ctx.context.options.emailVerification?.beforeEmailVerification) {\n\t\t\tawait ctx.context.options.emailVerification.beforeEmailVerification(\n\t\t\t\tuser.user,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t}\n\t\tif (ctx.context.options.emailVerification?.onEmailVerification) {\n\t\t\tawait ctx.context.options.emailVerification.onEmailVerification(\n\t\t\t\tuser.user,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t}\n\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\tparsed.email,\n\t\t\t{\n\t\t\t\temailVerified: true,\n\t\t\t},\n\t\t);\n\t\tif (ctx.context.options.emailVerification?.afterEmailVerification) {\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\t\t}\n\t\tif (ctx.context.options.emailVerification?.autoSignInAfterVerification) {\n\t\t\tconst currentSession = await getSessionFromCtx(ctx);\n\t\t\tif (!currentSession || currentSession.user.email !== parsed.email) {\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tuser.user.id,\n\t\t\t\t);\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...user.user,\n\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession: currentSession.session,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...currentSession.user,\n\t\t\t\t\t\temailVerified: true,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (ctx.query.callbackURL) {\n\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t\tuser: null,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as better_call832 from "better-call";
|
|
2
2
|
|
|
3
3
|
//#region src/api/routes/error.d.ts
|
|
4
|
-
declare const error:
|
|
4
|
+
declare const error: better_call832.StrictEndpoint<"/error", {
|
|
5
5
|
method: "GET";
|
|
6
6
|
metadata: {
|
|
7
7
|
openapi: {
|
package/dist/api/routes/ok.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as better_call789 from "better-call";
|
|
2
2
|
|
|
3
3
|
//#region src/api/routes/ok.d.ts
|
|
4
|
-
declare const ok:
|
|
4
|
+
declare const ok: better_call789.StrictEndpoint<"/ok", {
|
|
5
5
|
method: "GET";
|
|
6
6
|
metadata: {
|
|
7
7
|
openapi: {
|