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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.mjs","names":["tokens: OAuth2Tokens | undefined","defaultErrorURL","userInfo: Omit<User, \"createdAt\" | \"updatedAt\">","userInfo","toRedirectTo: string","toRedirectTo"],"sources":["../../../src/plugins/generic-oauth/routes.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport type { OAuth2Tokens, OAuth2UserInfo } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { decodeJwt } from \"jose\";\nimport * as z from \"zod\";\nimport { sessionMiddleware } from \"../../api\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport { generateState, parseState } from \"../../oauth2/state\";\nimport { setTokenUtil } from \"../../oauth2/utils\";\nimport type { User } from \"../../types\";\nimport { HIDE_METADATA } from \"../../utils\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport type { GenericOAuthOptions } from \"./types\";\n\nconst signInWithOAuth2BodySchema = z.object({\n\tproviderId: z.string().meta({\n\t\tdescription: \"The provider ID for the OAuth provider\",\n\t}),\n\tcallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The URL to redirect to after sign in\",\n\t\t})\n\t\t.optional(),\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The URL to redirect to if an error occurs\",\n\t\t})\n\t\t.optional(),\n\tnewUserCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t'The URL to redirect to after login if the user is new. Eg: \"/welcome\"',\n\t\t})\n\t\t.optional(),\n\tdisableRedirect: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription: \"Disable redirect\",\n\t\t})\n\t\t.optional(),\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription: \"Scopes to be passed to the provider authorization request.\",\n\t\t})\n\t\t.optional(),\n\trequestSignUp: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider. Eg: false\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Any additional data to pass through the oauth flow.\n\t */\n\tadditionalData: z.record(z.string(), z.any()).optional(),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/sign-in/oauth2`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.signInWithOAuth2`\n *\n * **client:**\n * `authClient.signIn.oauth2`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/sign-in#api-method-sign-in-oauth2)\n */\nexport const signInWithOAuth2 = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/oauth2\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: signInWithOAuth2BodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Sign in with OAuth2\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Sign in with OAuth2\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: GenericEndpointContext) => {\n\t\t\tconst { providerId } = ctx.body;\n\t\t\tconst config = options.config.find((c) => c.providerId === providerId);\n\t\t\tif (!config) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `${GENERIC_OAUTH_ERROR_CODES.PROVIDER_CONFIG_NOT_FOUND} ${providerId}`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tdiscoveryUrl,\n\t\t\t\tauthorizationUrl,\n\t\t\t\ttokenUrl,\n\t\t\t\tclientId,\n\t\t\t\tclientSecret,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI,\n\t\t\t\tresponseType,\n\t\t\t\tpkce,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tauthorizationUrlParams,\n\t\t\t\tresponseMode,\n\t\t\t} = config;\n\t\t\tlet finalAuthUrl = authorizationUrl;\n\t\t\tlet finalTokenUrl = tokenUrl;\n\t\t\tif (discoveryUrl) {\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t}>(discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: config.discoveryHeaders,\n\t\t\t\t\tonError(context) {\n\t\t\t\t\t\tctx.context.logger.error(context.error.message, context.error, {\n\t\t\t\t\t\t\tdiscoveryUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!finalAuthUrl || !finalTokenUrl) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (authorizationUrlParams) {\n\t\t\t\tconst withAdditionalParams = new URL(finalAuthUrl);\n\t\t\t\tfor (const [paramName, paramValue] of Object.entries(\n\t\t\t\t\tauthorizationUrlParams,\n\t\t\t\t)) {\n\t\t\t\t\twithAdditionalParams.searchParams.set(paramName, paramValue);\n\t\t\t\t}\n\t\t\t\tfinalAuthUrl = withAdditionalParams.toString();\n\t\t\t}\n\t\t\tconst additionalParams =\n\t\t\t\ttypeof authorizationUrlParams === \"function\"\n\t\t\t\t\t? authorizationUrlParams(ctx)\n\t\t\t\t\t: authorizationUrlParams;\n\n\t\t\tconst { state, codeVerifier } = await generateState(\n\t\t\t\tctx,\n\t\t\t\tundefined,\n\t\t\t\tctx.body.additionalData,\n\t\t\t);\n\t\t\tconst authUrl = await createAuthorizationURL({\n\t\t\t\tid: providerId,\n\t\t\t\toptions: {\n\t\t\t\t\tclientId,\n\t\t\t\t\tclientSecret,\n\t\t\t\t\tredirectURI,\n\t\t\t\t},\n\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier: pkce ? codeVerifier : undefined,\n\t\t\t\tscopes: ctx.body.scopes\n\t\t\t\t\t? [...ctx.body.scopes, ...(scopes || [])]\n\t\t\t\t\t: scopes || [],\n\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tresponseType,\n\t\t\t\tresponseMode,\n\t\t\t\tadditionalParams,\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\turl: authUrl.toString(),\n\t\t\t\tredirect: !ctx.body.disableRedirect,\n\t\t\t});\n\t\t},\n\t);\n\nconst OAuth2CallbackQuerySchema = z.object({\n\tcode: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The OAuth2 code\",\n\t\t})\n\t\t.optional(),\n\terror: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The error message, if any\",\n\t\t})\n\t\t.optional(),\n\terror_description: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The error description, if any\",\n\t\t})\n\t\t.optional(),\n\tstate: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The state parameter from the OAuth2 request\",\n\t\t})\n\t\t.optional(),\n});\n\nexport const oAuth2Callback = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/callback/:providerId\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: OAuth2CallbackQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: [\n\t\t\t\t\t\"application/x-www-form-urlencoded\",\n\t\t\t\t\t\"application/json\",\n\t\t\t\t],\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"OAuth2 callback\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"OAuth2 callback\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: GenericEndpointContext) => {\n\t\t\tconst defaultErrorURL =\n\t\t\t\tctx.context.options.onAPIError?.errorURL ||\n\t\t\t\t`${ctx.context.baseURL}/error`;\n\t\t\tif (ctx.query.error || !ctx.query.code) {\n\t\t\t\tthrow ctx.redirect(\n\t\t\t\t\t`${defaultErrorURL}?error=${\n\t\t\t\t\t\tctx.query.error || \"oAuth_code_missing\"\n\t\t\t\t\t}&error_description=${ctx.query.error_description}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst providerId = ctx.params?.providerId;\n\t\t\tif (!providerId) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.PROVIDER_ID_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst providerConfig = options.config.find(\n\t\t\t\t(p) => p.providerId === providerId,\n\t\t\t);\n\n\t\t\tif (!providerConfig) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `${GENERIC_OAUTH_ERROR_CODES.PROVIDER_CONFIG_NOT_FOUND} ${providerId}`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet tokens: OAuth2Tokens | undefined = undefined;\n\t\t\tconst parsedState = await parseState(ctx);\n\t\t\tconst {\n\t\t\t\tcallbackURL,\n\t\t\t\tcodeVerifier,\n\t\t\t\terrorURL,\n\t\t\t\trequestSignUp,\n\t\t\t\tnewUserURL,\n\t\t\t\tlink,\n\t\t\t} = parsedState;\n\t\t\tconst code = ctx.query.code;\n\n\t\t\tfunction redirectOnError(error: string) {\n\t\t\t\tconst defaultErrorURL =\n\t\t\t\t\tctx.context.options.onAPIError?.errorURL ||\n\t\t\t\t\t`${ctx.context.baseURL}/error`;\n\t\t\t\tlet url = errorURL || defaultErrorURL;\n\t\t\t\tif (url.includes(\"?\")) {\n\t\t\t\t\turl = `${url}&error=${error}`;\n\t\t\t\t} else {\n\t\t\t\t\turl = `${url}?error=${error}`;\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(url);\n\t\t\t}\n\n\t\t\tlet finalTokenUrl = providerConfig.tokenUrl;\n\t\t\tlet finalUserInfoUrl = providerConfig.userInfoUrl;\n\t\t\tif (providerConfig.discoveryUrl) {\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t}>(providerConfig.discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: providerConfig.discoveryHeaders,\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\t// Use custom getToken if provided\n\t\t\t\tif (providerConfig.getToken) {\n\t\t\t\t\ttokens = await providerConfig.getToken({\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerConfig.providerId}`,\n\t\t\t\t\t\tcodeVerifier: providerConfig.pkce ? codeVerifier : undefined,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Standard token exchange with tokenUrlParams support\n\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIG,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst additionalParams =\n\t\t\t\t\t\ttypeof providerConfig.tokenUrlParams === \"function\"\n\t\t\t\t\t\t\t? providerConfig.tokenUrlParams(ctx)\n\t\t\t\t\t\t\t: providerConfig.tokenUrlParams;\n\t\t\t\t\ttokens = await validateAuthorizationCode({\n\t\t\t\t\t\theaders: providerConfig.authorizationHeaders,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tcodeVerifier: providerConfig.pkce ? codeVerifier : undefined,\n\t\t\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerConfig.providerId}`,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: providerConfig.clientId,\n\t\t\t\t\t\t\tclientSecret: providerConfig.clientSecret,\n\t\t\t\t\t\t\tredirectURI: providerConfig.redirectURI,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\tauthentication: providerConfig.authentication,\n\t\t\t\t\t\tadditionalParams,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\te && typeof e === \"object\" && \"name\" in e ? (e.name as string) : \"\",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t\tthrow redirectOnError(\"oauth_code_verification_failed\");\n\t\t\t}\n\t\t\tif (!tokens) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIG,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst userInfo: Omit<User, \"createdAt\" | \"updatedAt\"> =\n\t\t\t\tawait (async function handleUserInfo() {\n\t\t\t\t\tconst userInfo = (\n\t\t\t\t\t\tproviderConfig.getUserInfo\n\t\t\t\t\t\t\t? await providerConfig.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl)\n\t\t\t\t\t) as OAuth2UserInfo | null;\n\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\tthrow redirectOnError(\"user_info_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\tconst mapUser = providerConfig.mapProfileToUser\n\t\t\t\t\t\t? await providerConfig.mapProfileToUser(userInfo)\n\t\t\t\t\t\t: userInfo;\n\t\t\t\t\tconst email = mapUser.email\n\t\t\t\t\t\t? mapUser.email.toLowerCase()\n\t\t\t\t\t\t: userInfo.email?.toLowerCase();\n\t\t\t\t\tif (!email) {\n\t\t\t\t\t\tctx.context.logger.error(\"Unable to get user info\", userInfo);\n\t\t\t\t\t\tthrow redirectOnError(\"email_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\tconst id = mapUser.id ? String(mapUser.id) : String(userInfo.id);\n\t\t\t\t\tconst name = mapUser.name ? mapUser.name : userInfo.name;\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tctx.context.logger.error(\"Unable to get user info\", userInfo);\n\t\t\t\t\t\tthrow redirectOnError(\"name_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...userInfo,\n\t\t\t\t\t\t...mapUser,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname,\n\t\t\t\t\t};\n\t\t\t\t})();\n\t\t\tif (link) {\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.account?.accountLinking?.allowDifferentEmails !==\n\t\t\t\t\t\ttrue &&\n\t\t\t\t\tlink.email !== userInfo.email\n\t\t\t\t) {\n\t\t\t\t\treturn redirectOnError(\"email_doesn't_match\");\n\t\t\t\t}\n\t\t\t\tconst existingAccount =\n\t\t\t\t\tawait ctx.context.internalAdapter.findAccountByProviderId(\n\t\t\t\t\t\tString(userInfo.id),\n\t\t\t\t\t\tproviderConfig.providerId,\n\t\t\t\t\t);\n\t\t\t\tif (existingAccount) {\n\t\t\t\t\tif (existingAccount.userId !== link.userId) {\n\t\t\t\t\t\treturn redirectOnError(\"account_already_linked_to_different_user\");\n\t\t\t\t\t}\n\t\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\t\tObject.entries({\n\t\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\t\trefreshToken: await setTokenUtil(\n\t\t\t\t\t\t\t\ttokens.refreshToken,\n\t\t\t\t\t\t\t\tctx.context,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t\t);\n\t\t\t\t\tawait ctx.context.internalAdapter.updateAccount(\n\t\t\t\t\t\texistingAccount.id,\n\t\t\t\t\t\tupdateData,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconst newAccount = await ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\tuserId: link.userId,\n\t\t\t\t\t\tproviderId: providerConfig.providerId,\n\t\t\t\t\t\taccountId: userInfo.id,\n\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\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\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t});\n\t\t\t\t\tif (!newAccount) {\n\t\t\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet toRedirectTo: string;\n\t\t\t\ttry {\n\t\t\t\t\tconst url = callbackURL;\n\t\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t\t} catch {\n\t\t\t\t\ttoRedirectTo = callbackURL;\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(toRedirectTo);\n\t\t\t}\n\n\t\t\tconst result = await handleOAuthUserInfo(ctx, {\n\t\t\t\tuserInfo,\n\t\t\t\taccount: {\n\t\t\t\t\tproviderId: providerConfig.providerId,\n\t\t\t\t\taccountId: userInfo.id,\n\t\t\t\t\t...tokens,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t},\n\t\t\t\tcallbackURL: callbackURL,\n\t\t\t\tdisableSignUp:\n\t\t\t\t\t(providerConfig.disableImplicitSignUp && !requestSignUp) ||\n\t\t\t\t\tproviderConfig.disableSignUp,\n\t\t\t\toverrideUserInfo: providerConfig.overrideUserInfo,\n\t\t\t});\n\n\t\t\tif (result.error) {\n\t\t\t\treturn redirectOnError(result.error.split(\" \").join(\"_\"));\n\t\t\t}\n\t\t\tconst { session, user } = result.data!;\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession,\n\t\t\t\tuser,\n\t\t\t});\n\t\t\tlet toRedirectTo: string;\n\t\t\ttry {\n\t\t\t\tconst url = result.isRegister ? newUserURL || callbackURL : callbackURL;\n\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t} catch {\n\t\t\t\ttoRedirectTo = result.isRegister\n\t\t\t\t\t? newUserURL || callbackURL\n\t\t\t\t\t: callbackURL;\n\t\t\t}\n\t\t\tthrow ctx.redirect(toRedirectTo);\n\t\t},\n\t);\n\nconst OAuth2LinkAccountBodySchema = z.object({\n\tproviderId: z.string(),\n\t/**\n\t * Callback URL to redirect to after the user has signed in.\n\t */\n\tcallbackURL: z.string(),\n\t/**\n\t * Additional scopes to request when linking the account.\n\t * This is useful for requesting additional permissions when\n\t * linking a social account compared to the initial authentication.\n\t */\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription: \"Additional scopes to request when linking the account\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * The URL to redirect to if there is an error during the link process.\n\t */\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"The URL to redirect to if there is an error during the link process\",\n\t\t})\n\t\t.optional(),\n});\n/**\n * ### Endpoint\n *\n * POST `/oauth2/link`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.oAuth2LinkAccount`\n *\n * **client:**\n * `authClient.oauth2.link`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/generic-oauth#api-method-oauth2-link)\n */\nexport const oAuth2LinkAccount = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/link\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: OAuth2LinkAccountBodySchema,\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Link an OAuth2 account to the current user session\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Authorization URL generated successfully for linking an OAuth2 account\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The authorization URL to redirect the user to for linking the OAuth2 account\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates that the client should redirect to the provided URL\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [true],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"url\", \"redirect\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (c: GenericEndpointContext) => {\n\t\t\tconst session = c.context.session;\n\t\t\tif (!session) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.SESSION_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst provider = options.config.find(\n\t\t\t\t(p) => p.providerId === c.body.providerId,\n\t\t\t);\n\t\t\tif (!provider) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tproviderId,\n\t\t\t\tclientId,\n\t\t\t\tclientSecret,\n\t\t\t\tredirectURI,\n\t\t\t\tauthorizationUrl,\n\t\t\t\tdiscoveryUrl,\n\t\t\t\tpkce,\n\t\t\t\tscopes,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tauthorizationUrlParams,\n\t\t\t} = provider;\n\n\t\t\tlet finalAuthUrl = authorizationUrl;\n\t\t\tif (!finalAuthUrl) {\n\t\t\t\tif (!discoveryUrl) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t}>(discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: provider.discoveryHeaders,\n\t\t\t\t\tonError(context) {\n\t\t\t\t\t\tc.context.logger.error(context.error.message, context.error, {\n\t\t\t\t\t\t\tdiscoveryUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!finalAuthUrl) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst state = await generateState(\n\t\t\t\tc,\n\t\t\t\t{\n\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\temail: session.user.email,\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t);\n\n\t\t\tconst additionalParams =\n\t\t\t\ttypeof authorizationUrlParams === \"function\"\n\t\t\t\t\t? authorizationUrlParams(c)\n\t\t\t\t\t: authorizationUrlParams;\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: providerId,\n\t\t\t\toptions: {\n\t\t\t\t\tclientId,\n\t\t\t\t\tclientSecret,\n\t\t\t\t\tredirectURI:\n\t\t\t\t\t\tredirectURI || `${c.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\t},\n\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\tstate: state.state,\n\t\t\t\tcodeVerifier: pkce ? state.codeVerifier : undefined,\n\t\t\t\tscopes: c.body.scopes || scopes || [],\n\t\t\t\tredirectURI:\n\t\t\t\t\tredirectURI || `${c.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tadditionalParams,\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\turl: url.toString(),\n\t\t\t\tredirect: true,\n\t\t\t});\n\t\t},\n\t);\n\nexport async function getUserInfo(\n\ttokens: OAuth2Tokens,\n\tfinalUserInfoUrl: string | undefined,\n): Promise<OAuth2UserInfo | null> {\n\tif (tokens.idToken) {\n\t\tconst decoded = decodeJwt(tokens.idToken) as {\n\t\t\tsub: string;\n\t\t\temail_verified: boolean;\n\t\t\temail: string;\n\t\t\tname: string;\n\t\t\tpicture: string;\n\t\t};\n\t\tif (decoded) {\n\t\t\tif (decoded.sub && decoded.email) {\n\t\t\t\treturn {\n\t\t\t\t\tid: decoded.sub,\n\t\t\t\t\temailVerified: decoded.email_verified,\n\t\t\t\t\timage: decoded.picture,\n\t\t\t\t\t...decoded,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!finalUserInfoUrl) {\n\t\treturn null;\n\t}\n\n\tconst userInfo = await betterFetch<{\n\t\temail: string;\n\t\tsub?: string | undefined;\n\t\tname: string;\n\t\temail_verified: boolean;\n\t\tpicture: string;\n\t}>(finalUserInfoUrl, {\n\t\tmethod: \"GET\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${tokens.accessToken}`,\n\t\t},\n\t});\n\treturn {\n\t\tid: userInfo.data?.sub ?? \"\",\n\t\temailVerified: userInfo.data?.email_verified ?? false,\n\t\temail: userInfo.data?.email,\n\t\timage: userInfo.data?.picture,\n\t\tname: userInfo.data?.name,\n\t\t...userInfo.data,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"routes.mjs","names":["tokens: OAuth2Tokens | undefined","defaultErrorURL","userInfo: Omit<User, \"createdAt\" | \"updatedAt\">","userInfo","toRedirectTo: string","toRedirectTo"],"sources":["../../../src/plugins/generic-oauth/routes.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport type { OAuth2Tokens, OAuth2UserInfo } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { decodeJwt } from \"jose\";\nimport * as z from \"zod\";\nimport { sessionMiddleware } from \"../../api\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport { generateState, parseState } from \"../../oauth2/state\";\nimport { setTokenUtil } from \"../../oauth2/utils\";\nimport type { User } from \"../../types\";\nimport { HIDE_METADATA } from \"../../utils\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport type { GenericOAuthOptions } from \"./types\";\n\nconst signInWithOAuth2BodySchema = z.object({\n\tproviderId: z.string().meta({\n\t\tdescription: \"The provider ID for the OAuth provider\",\n\t}),\n\tcallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The URL to redirect to after sign in\",\n\t\t})\n\t\t.optional(),\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The URL to redirect to if an error occurs\",\n\t\t})\n\t\t.optional(),\n\tnewUserCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t'The URL to redirect to after login if the user is new. Eg: \"/welcome\"',\n\t\t})\n\t\t.optional(),\n\tdisableRedirect: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription: \"Disable redirect\",\n\t\t})\n\t\t.optional(),\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription: \"Scopes to be passed to the provider authorization request.\",\n\t\t})\n\t\t.optional(),\n\trequestSignUp: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider. Eg: false\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Any additional data to pass through the oauth flow.\n\t */\n\tadditionalData: z.record(z.string(), z.any()).optional(),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/sign-in/oauth2`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.signInWithOAuth2`\n *\n * **client:**\n * `authClient.signIn.oauth2`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/sign-in#api-method-sign-in-oauth2)\n */\nexport const signInWithOAuth2 = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/oauth2\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: signInWithOAuth2BodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Sign in with OAuth2\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Sign in with OAuth2\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: GenericEndpointContext) => {\n\t\t\tconst { providerId } = ctx.body;\n\t\t\tconst config = options.config.find((c) => c.providerId === providerId);\n\t\t\tif (!config) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `${GENERIC_OAUTH_ERROR_CODES.PROVIDER_CONFIG_NOT_FOUND} ${providerId}`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tdiscoveryUrl,\n\t\t\t\tauthorizationUrl,\n\t\t\t\ttokenUrl,\n\t\t\t\tclientId,\n\t\t\t\tclientSecret,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI,\n\t\t\t\tresponseType,\n\t\t\t\tpkce,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tauthorizationUrlParams,\n\t\t\t\tresponseMode,\n\t\t\t} = config;\n\t\t\tlet finalAuthUrl = authorizationUrl;\n\t\t\tlet finalTokenUrl = tokenUrl;\n\t\t\tif (discoveryUrl) {\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t}>(discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: config.discoveryHeaders,\n\t\t\t\t\tonError(context) {\n\t\t\t\t\t\tctx.context.logger.error(context.error.message, context.error, {\n\t\t\t\t\t\t\tdiscoveryUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!finalAuthUrl || !finalTokenUrl) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (authorizationUrlParams) {\n\t\t\t\tconst withAdditionalParams = new URL(finalAuthUrl);\n\t\t\t\tfor (const [paramName, paramValue] of Object.entries(\n\t\t\t\t\tauthorizationUrlParams,\n\t\t\t\t)) {\n\t\t\t\t\twithAdditionalParams.searchParams.set(paramName, paramValue);\n\t\t\t\t}\n\t\t\t\tfinalAuthUrl = withAdditionalParams.toString();\n\t\t\t}\n\t\t\tconst additionalParams =\n\t\t\t\ttypeof authorizationUrlParams === \"function\"\n\t\t\t\t\t? authorizationUrlParams(ctx)\n\t\t\t\t\t: authorizationUrlParams;\n\n\t\t\tconst { state, codeVerifier } = await generateState(\n\t\t\t\tctx,\n\t\t\t\tundefined,\n\t\t\t\tctx.body.additionalData,\n\t\t\t);\n\t\t\tconst authUrl = await createAuthorizationURL({\n\t\t\t\tid: providerId,\n\t\t\t\toptions: {\n\t\t\t\t\tclientId,\n\t\t\t\t\tclientSecret,\n\t\t\t\t\tredirectURI,\n\t\t\t\t},\n\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier: pkce ? codeVerifier : undefined,\n\t\t\t\tscopes: ctx.body.scopes\n\t\t\t\t\t? [...ctx.body.scopes, ...(scopes || [])]\n\t\t\t\t\t: scopes || [],\n\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tresponseType,\n\t\t\t\tresponseMode,\n\t\t\t\tadditionalParams,\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\turl: authUrl.toString(),\n\t\t\t\tredirect: !ctx.body.disableRedirect,\n\t\t\t});\n\t\t},\n\t);\n\nconst OAuth2CallbackQuerySchema = z.object({\n\tcode: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The OAuth2 code\",\n\t\t})\n\t\t.optional(),\n\terror: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The error message, if any\",\n\t\t})\n\t\t.optional(),\n\terror_description: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The error description, if any\",\n\t\t})\n\t\t.optional(),\n\tstate: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The state parameter from the OAuth2 request\",\n\t\t})\n\t\t.optional(),\n\tiss: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The issuer identifier\",\n\t\t})\n\t\t.optional(),\n});\n\nexport const oAuth2Callback = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/callback/:providerId\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: OAuth2CallbackQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: [\n\t\t\t\t\t\"application/x-www-form-urlencoded\",\n\t\t\t\t\t\"application/json\",\n\t\t\t\t],\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"OAuth2 callback\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"OAuth2 callback\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: GenericEndpointContext) => {\n\t\t\tconst defaultErrorURL =\n\t\t\t\tctx.context.options.onAPIError?.errorURL ||\n\t\t\t\t`${ctx.context.baseURL}/error`;\n\t\t\tif (ctx.query.error || !ctx.query.code) {\n\t\t\t\tthrow ctx.redirect(\n\t\t\t\t\t`${defaultErrorURL}?error=${\n\t\t\t\t\t\tctx.query.error || \"oAuth_code_missing\"\n\t\t\t\t\t}&error_description=${ctx.query.error_description}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst providerId = ctx.params?.providerId;\n\t\t\tif (!providerId) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.PROVIDER_ID_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst providerConfig = options.config.find(\n\t\t\t\t(p) => p.providerId === providerId,\n\t\t\t);\n\n\t\t\tif (!providerConfig) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `${GENERIC_OAUTH_ERROR_CODES.PROVIDER_CONFIG_NOT_FOUND} ${providerId}`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet tokens: OAuth2Tokens | undefined = undefined;\n\t\t\tconst parsedState = await parseState(ctx);\n\t\t\tconst {\n\t\t\t\tcallbackURL,\n\t\t\t\tcodeVerifier,\n\t\t\t\terrorURL,\n\t\t\t\trequestSignUp,\n\t\t\t\tnewUserURL,\n\t\t\t\tlink,\n\t\t\t} = parsedState;\n\t\t\tconst code = ctx.query.code;\n\n\t\t\tfunction redirectOnError(error: string) {\n\t\t\t\tconst defaultErrorURL =\n\t\t\t\t\tctx.context.options.onAPIError?.errorURL ||\n\t\t\t\t\t`${ctx.context.baseURL}/error`;\n\t\t\t\tlet url = errorURL || defaultErrorURL;\n\t\t\t\tif (url.includes(\"?\")) {\n\t\t\t\t\turl = `${url}&error=${error}`;\n\t\t\t\t} else {\n\t\t\t\t\turl = `${url}?error=${error}`;\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(url);\n\t\t\t}\n\n\t\t\tlet finalTokenUrl = providerConfig.tokenUrl;\n\t\t\tlet finalUserInfoUrl = providerConfig.userInfoUrl;\n\t\t\tlet expectedIssuer = providerConfig.issuer;\n\n\t\t\tif (providerConfig.discoveryUrl) {\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\tissuer: string;\n\t\t\t\t}>(providerConfig.discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: providerConfig.discoveryHeaders,\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t\tif (!expectedIssuer && discovery.data.issuer) {\n\t\t\t\t\t\texpectedIssuer = discovery.data.issuer;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (expectedIssuer) {\n\t\t\t\tif (ctx.query.iss) {\n\t\t\t\t\tif (ctx.query.iss !== expectedIssuer) {\n\t\t\t\t\t\tctx.context.logger.error(\"OAuth issuer mismatch\", {\n\t\t\t\t\t\t\texpected: expectedIssuer,\n\t\t\t\t\t\t\treceived: ctx.query.iss,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn redirectOnError(\"issuer_mismatch\");\n\t\t\t\t\t}\n\t\t\t\t} else if (providerConfig.requireIssuerValidation) {\n\t\t\t\t\tctx.context.logger.error(\"OAuth issuer parameter missing\", {\n\t\t\t\t\t\texpected: expectedIssuer,\n\t\t\t\t\t});\n\t\t\t\t\treturn redirectOnError(\"issuer_missing\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Use custom getToken if provided\n\t\t\t\tif (providerConfig.getToken) {\n\t\t\t\t\ttokens = await providerConfig.getToken({\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerConfig.providerId}`,\n\t\t\t\t\t\tcodeVerifier: providerConfig.pkce ? codeVerifier : undefined,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Standard token exchange with tokenUrlParams support\n\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIG,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst additionalParams =\n\t\t\t\t\t\ttypeof providerConfig.tokenUrlParams === \"function\"\n\t\t\t\t\t\t\t? providerConfig.tokenUrlParams(ctx)\n\t\t\t\t\t\t\t: providerConfig.tokenUrlParams;\n\t\t\t\t\ttokens = await validateAuthorizationCode({\n\t\t\t\t\t\theaders: providerConfig.authorizationHeaders,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tcodeVerifier: providerConfig.pkce ? codeVerifier : undefined,\n\t\t\t\t\t\tredirectURI: `${ctx.context.baseURL}/oauth2/callback/${providerConfig.providerId}`,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: providerConfig.clientId,\n\t\t\t\t\t\t\tclientSecret: providerConfig.clientSecret,\n\t\t\t\t\t\t\tredirectURI: providerConfig.redirectURI,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\tauthentication: providerConfig.authentication,\n\t\t\t\t\t\tadditionalParams,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\te && typeof e === \"object\" && \"name\" in e ? (e.name as string) : \"\",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t\tthrow redirectOnError(\"oauth_code_verification_failed\");\n\t\t\t}\n\t\t\tif (!tokens) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIG,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst userInfo: Omit<User, \"createdAt\" | \"updatedAt\"> =\n\t\t\t\tawait (async function handleUserInfo() {\n\t\t\t\t\tconst userInfo = (\n\t\t\t\t\t\tproviderConfig.getUserInfo\n\t\t\t\t\t\t\t? await providerConfig.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl)\n\t\t\t\t\t) as OAuth2UserInfo | null;\n\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\tthrow redirectOnError(\"user_info_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\tconst mapUser = providerConfig.mapProfileToUser\n\t\t\t\t\t\t? await providerConfig.mapProfileToUser(userInfo)\n\t\t\t\t\t\t: userInfo;\n\t\t\t\t\tconst email = mapUser.email\n\t\t\t\t\t\t? mapUser.email.toLowerCase()\n\t\t\t\t\t\t: userInfo.email?.toLowerCase();\n\t\t\t\t\tif (!email) {\n\t\t\t\t\t\tctx.context.logger.error(\"Unable to get user info\", userInfo);\n\t\t\t\t\t\tthrow redirectOnError(\"email_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\tconst id = mapUser.id ? String(mapUser.id) : String(userInfo.id);\n\t\t\t\t\tconst name = mapUser.name ? mapUser.name : userInfo.name;\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tctx.context.logger.error(\"Unable to get user info\", userInfo);\n\t\t\t\t\t\tthrow redirectOnError(\"name_is_missing\");\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...userInfo,\n\t\t\t\t\t\t...mapUser,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname,\n\t\t\t\t\t};\n\t\t\t\t})();\n\t\t\tif (link) {\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.account?.accountLinking?.allowDifferentEmails !==\n\t\t\t\t\t\ttrue &&\n\t\t\t\t\tlink.email.toLowerCase() !== userInfo.email.toLowerCase()\n\t\t\t\t) {\n\t\t\t\t\treturn redirectOnError(\"email_doesn't_match\");\n\t\t\t\t}\n\t\t\t\tconst existingAccount =\n\t\t\t\t\tawait ctx.context.internalAdapter.findAccountByProviderId(\n\t\t\t\t\t\tString(userInfo.id),\n\t\t\t\t\t\tproviderConfig.providerId,\n\t\t\t\t\t);\n\t\t\t\tif (existingAccount) {\n\t\t\t\t\tif (existingAccount.userId !== link.userId) {\n\t\t\t\t\t\treturn redirectOnError(\"account_already_linked_to_different_user\");\n\t\t\t\t\t}\n\t\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\t\tObject.entries({\n\t\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\n\t\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\t\trefreshToken: await setTokenUtil(\n\t\t\t\t\t\t\t\ttokens.refreshToken,\n\t\t\t\t\t\t\t\tctx.context,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\taccessTokenExpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t\t\trefreshTokenExpiresAt: tokens.refreshTokenExpiresAt,\n\t\t\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t\t);\n\t\t\t\t\tawait ctx.context.internalAdapter.updateAccount(\n\t\t\t\t\t\texistingAccount.id,\n\t\t\t\t\t\tupdateData,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconst newAccount = await ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\tuserId: link.userId,\n\t\t\t\t\t\tproviderId: providerConfig.providerId,\n\t\t\t\t\t\taccountId: userInfo.id,\n\t\t\t\t\t\taccessToken: await setTokenUtil(tokens.accessToken, ctx.context),\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\trefreshToken: await setTokenUtil(tokens.refreshToken, ctx.context),\n\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t});\n\t\t\t\t\tif (!newAccount) {\n\t\t\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet toRedirectTo: string;\n\t\t\t\ttry {\n\t\t\t\t\tconst url = callbackURL;\n\t\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t\t} catch {\n\t\t\t\t\ttoRedirectTo = callbackURL;\n\t\t\t\t}\n\t\t\t\tthrow ctx.redirect(toRedirectTo);\n\t\t\t}\n\n\t\t\tconst result = await handleOAuthUserInfo(ctx, {\n\t\t\t\tuserInfo,\n\t\t\t\taccount: {\n\t\t\t\t\tproviderId: providerConfig.providerId,\n\t\t\t\t\taccountId: userInfo.id,\n\t\t\t\t\t...tokens,\n\t\t\t\t\tscope: tokens.scopes?.join(\",\"),\n\t\t\t\t},\n\t\t\t\tcallbackURL: callbackURL,\n\t\t\t\tdisableSignUp:\n\t\t\t\t\t(providerConfig.disableImplicitSignUp && !requestSignUp) ||\n\t\t\t\t\tproviderConfig.disableSignUp,\n\t\t\t\toverrideUserInfo: providerConfig.overrideUserInfo,\n\t\t\t});\n\n\t\t\tif (result.error) {\n\t\t\t\treturn redirectOnError(result.error.split(\" \").join(\"_\"));\n\t\t\t}\n\t\t\tconst { session, user } = result.data!;\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession,\n\t\t\t\tuser,\n\t\t\t});\n\t\t\tlet toRedirectTo: string;\n\t\t\ttry {\n\t\t\t\tconst url = result.isRegister ? newUserURL || callbackURL : callbackURL;\n\t\t\t\ttoRedirectTo = url.toString();\n\t\t\t} catch {\n\t\t\t\ttoRedirectTo = result.isRegister\n\t\t\t\t\t? newUserURL || callbackURL\n\t\t\t\t\t: callbackURL;\n\t\t\t}\n\t\t\tthrow ctx.redirect(toRedirectTo);\n\t\t},\n\t);\n\nconst OAuth2LinkAccountBodySchema = z.object({\n\tproviderId: z.string(),\n\t/**\n\t * Callback URL to redirect to after the user has signed in.\n\t */\n\tcallbackURL: z.string(),\n\t/**\n\t * Additional scopes to request when linking the account.\n\t * This is useful for requesting additional permissions when\n\t * linking a social account compared to the initial authentication.\n\t */\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription: \"Additional scopes to request when linking the account\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * The URL to redirect to if there is an error during the link process.\n\t */\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"The URL to redirect to if there is an error during the link process\",\n\t\t})\n\t\t.optional(),\n});\n/**\n * ### Endpoint\n *\n * POST `/oauth2/link`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.oAuth2LinkAccount`\n *\n * **client:**\n * `authClient.oauth2.link`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/generic-oauth#api-method-oauth2-link)\n */\nexport const oAuth2LinkAccount = (options: GenericOAuthOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/link\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: OAuth2LinkAccountBodySchema,\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Link an OAuth2 account to the current user session\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Authorization URL generated successfully for linking an OAuth2 account\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\turl: {\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: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The authorization URL to redirect the user to for linking the OAuth2 account\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates that the client should redirect to the provided URL\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [true],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"url\", \"redirect\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (c: GenericEndpointContext) => {\n\t\t\tconst session = c.context.session;\n\t\t\tif (!session) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.SESSION_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst provider = options.config.find(\n\t\t\t\t(p) => p.providerId === c.body.providerId,\n\t\t\t);\n\t\t\tif (!provider) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tproviderId,\n\t\t\t\tclientId,\n\t\t\t\tclientSecret,\n\t\t\t\tredirectURI,\n\t\t\t\tauthorizationUrl,\n\t\t\t\tdiscoveryUrl,\n\t\t\t\tpkce,\n\t\t\t\tscopes,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tauthorizationUrlParams,\n\t\t\t} = provider;\n\n\t\t\tlet finalAuthUrl = authorizationUrl;\n\t\t\tif (!finalAuthUrl) {\n\t\t\t\tif (!discoveryUrl) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t}>(discoveryUrl, {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: provider.discoveryHeaders,\n\t\t\t\t\tonError(context) {\n\t\t\t\t\t\tc.context.logger.error(context.error.message, context.error, {\n\t\t\t\t\t\t\tdiscoveryUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (discovery.data) {\n\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!finalAuthUrl) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst state = await generateState(\n\t\t\t\tc,\n\t\t\t\t{\n\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\temail: session.user.email,\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t);\n\n\t\t\tconst additionalParams =\n\t\t\t\ttypeof authorizationUrlParams === \"function\"\n\t\t\t\t\t? authorizationUrlParams(c)\n\t\t\t\t\t: authorizationUrlParams;\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: providerId,\n\t\t\t\toptions: {\n\t\t\t\t\tclientId,\n\t\t\t\t\tclientSecret,\n\t\t\t\t\tredirectURI:\n\t\t\t\t\t\tredirectURI || `${c.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\t},\n\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\tstate: state.state,\n\t\t\t\tcodeVerifier: pkce ? state.codeVerifier : undefined,\n\t\t\t\tscopes: c.body.scopes || scopes || [],\n\t\t\t\tredirectURI:\n\t\t\t\t\tredirectURI || `${c.context.baseURL}/oauth2/callback/${providerId}`,\n\t\t\t\tprompt,\n\t\t\t\taccessType,\n\t\t\t\tadditionalParams,\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\turl: url.toString(),\n\t\t\t\tredirect: true,\n\t\t\t});\n\t\t},\n\t);\n\nexport async function getUserInfo(\n\ttokens: OAuth2Tokens,\n\tfinalUserInfoUrl: string | undefined,\n): Promise<OAuth2UserInfo | null> {\n\tif (tokens.idToken) {\n\t\tconst decoded = decodeJwt(tokens.idToken) as {\n\t\t\tsub: string;\n\t\t\temail_verified: boolean;\n\t\t\temail: string;\n\t\t\tname: string;\n\t\t\tpicture: string;\n\t\t};\n\t\tif (decoded) {\n\t\t\tif (decoded.sub && decoded.email) {\n\t\t\t\treturn {\n\t\t\t\t\tid: decoded.sub,\n\t\t\t\t\temailVerified: decoded.email_verified,\n\t\t\t\t\timage: decoded.picture,\n\t\t\t\t\t...decoded,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!finalUserInfoUrl) {\n\t\treturn null;\n\t}\n\n\tconst userInfo = await betterFetch<{\n\t\temail: string;\n\t\tsub?: string | undefined;\n\t\tname: string;\n\t\temail_verified: boolean;\n\t\tpicture: string;\n\t}>(finalUserInfoUrl, {\n\t\tmethod: \"GET\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${tokens.accessToken}`,\n\t\t},\n\t});\n\treturn {\n\t\tid: userInfo.data?.sub ?? \"\",\n\t\temailVerified: userInfo.data?.email_verified ?? false,\n\t\temail: userInfo.data?.email,\n\t\timage: userInfo.data?.picture,\n\t\tname: userInfo.data?.name,\n\t\t...userInfo.data,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,MAAM,6BAA6B,EAAE,OAAO;CAC3C,YAAY,EAAE,QAAQ,CAAC,KAAK,EAC3B,aAAa,0CACb,CAAC;CACF,aAAa,EACX,QAAQ,CACR,KAAK,EACL,aAAa,wCACb,CAAC,CACD,UAAU;CACZ,kBAAkB,EAChB,QAAQ,CACR,KAAK,EACL,aAAa,6CACb,CAAC,CACD,UAAU;CACZ,oBAAoB,EAClB,QAAQ,CACR,KAAK,EACL,aACC,2EACD,CAAC,CACD,UAAU;CACZ,iBAAiB,EACf,SAAS,CACT,KAAK,EACL,aAAa,oBACb,CAAC,CACD,UAAU;CACZ,QAAQ,EACN,MAAM,EAAE,QAAQ,CAAC,CACjB,KAAK,EACL,aAAa,8DACb,CAAC,CACD,UAAU;CACZ,eAAe,EACb,SAAS,CACT,KAAK,EACL,aACC,sGACD,CAAC,CACD,UAAU;CAIZ,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC,UAAU;CACxD,CAAC;;;;;;;;;;;;;;;;AAiBF,MAAa,oBAAoB,YAChC,mBACC,mBACA;CACC,QAAQ;CACR,MAAM;CACN,UAAU,EACT,SAAS;EACR,aAAa;EACb,WAAW,EACV,KAAK;GACJ,aAAa;GACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY;KACX,KAAK,EACJ,MAAM,UACN;KACD,UAAU,EACT,MAAM,WACN;KACD;IACD,EACD,EACD;GACD,EACD;EACD,EACD;CACD,EACD,OAAO,QAAgC;CACtC,MAAM,EAAE,eAAe,IAAI;CAC3B,MAAM,SAAS,QAAQ,OAAO,MAAM,MAAM,EAAE,eAAe,WAAW;AACtE,KAAI,CAAC,OACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,GAAG,0BAA0B,0BAA0B,GAAG,cACnE,CAAC;CAEH,MAAM,EACL,cACA,kBACA,UACA,UACA,cACA,QACA,aACA,cACA,MACA,QACA,YACA,wBACA,iBACG;CACJ,IAAI,eAAe;CACnB,IAAI,gBAAgB;AACpB,KAAI,cAAc;EACjB,MAAM,YAAY,MAAM,YAGrB,cAAc;GAChB,QAAQ;GACR,SAAS,OAAO;GAChB,QAAQ,SAAS;AAChB,QAAI,QAAQ,OAAO,MAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO,EAC9D,cACA,CAAC;;GAEH,CAAC;AACF,MAAI,UAAU,MAAM;AACnB,kBAAe,UAAU,KAAK;AAC9B,mBAAgB,UAAU,KAAK;;;AAGjC,KAAI,CAAC,gBAAgB,CAAC,cACrB,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,6BACnC,CAAC;AAEH,KAAI,wBAAwB;EAC3B,MAAM,uBAAuB,IAAI,IAAI,aAAa;AAClD,OAAK,MAAM,CAAC,WAAW,eAAe,OAAO,QAC5C,uBACA,CACA,sBAAqB,aAAa,IAAI,WAAW,WAAW;AAE7D,iBAAe,qBAAqB,UAAU;;CAE/C,MAAM,mBACL,OAAO,2BAA2B,aAC/B,uBAAuB,IAAI,GAC3B;CAEJ,MAAM,EAAE,OAAO,iBAAiB,MAAM,cACrC,KACA,QACA,IAAI,KAAK,eACT;CACD,MAAM,UAAU,MAAM,uBAAuB;EAC5C,IAAI;EACJ,SAAS;GACR;GACA;GACA;GACA;EACD,uBAAuB;EACvB;EACA,cAAc,OAAO,eAAe;EACpC,QAAQ,IAAI,KAAK,SACd,CAAC,GAAG,IAAI,KAAK,QAAQ,GAAI,UAAU,EAAE,CAAE,GACvC,UAAU,EAAE;EACf,aAAa,GAAG,IAAI,QAAQ,QAAQ,mBAAmB;EACvD;EACA;EACA;EACA;EACA;EACA,CAAC;AACF,QAAO,IAAI,KAAK;EACf,KAAK,QAAQ,UAAU;EACvB,UAAU,CAAC,IAAI,KAAK;EACpB,CAAC;EAEH;AAEF,MAAM,4BAA4B,EAAE,OAAO;CAC1C,MAAM,EACJ,QAAQ,CACR,KAAK,EACL,aAAa,mBACb,CAAC,CACD,UAAU;CACZ,OAAO,EACL,QAAQ,CACR,KAAK,EACL,aAAa,6BACb,CAAC,CACD,UAAU;CACZ,mBAAmB,EACjB,QAAQ,CACR,KAAK,EACL,aAAa,iCACb,CAAC,CACD,UAAU;CACZ,OAAO,EACL,QAAQ,CACR,KAAK,EACL,aAAa,+CACb,CAAC,CACD,UAAU;CACZ,KAAK,EACH,QAAQ,CACR,KAAK,EACL,aAAa,yBACb,CAAC,CACD,UAAU;CACZ,CAAC;AAEF,MAAa,kBAAkB,YAC9B,mBACC,gCACA;CACC,QAAQ;CACR,OAAO;CACP,UAAU;EACT,GAAG;EACH,mBAAmB,CAClB,qCACA,mBACA;EACD,SAAS;GACR,aAAa;GACb,WAAW,EACV,KAAK;IACJ,aAAa;IACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;KACP,MAAM;KACN,YAAY,EACX,KAAK,EACJ,MAAM,UACN,EACD;KACD,EACD,EACD;IACD,EACD;GACD;EACD;CACD,EACD,OAAO,QAAgC;CACtC,MAAM,kBACL,IAAI,QAAQ,QAAQ,YAAY,YAChC,GAAG,IAAI,QAAQ,QAAQ;AACxB,KAAI,IAAI,MAAM,SAAS,CAAC,IAAI,MAAM,KACjC,OAAM,IAAI,SACT,GAAG,gBAAgB,SAClB,IAAI,MAAM,SAAS,qBACnB,qBAAqB,IAAI,MAAM,oBAChC;CAEF,MAAM,aAAa,IAAI,QAAQ;AAC/B,KAAI,CAAC,WACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,sBACnC,CAAC;CAEH,MAAM,iBAAiB,QAAQ,OAAO,MACpC,MAAM,EAAE,eAAe,WACxB;AAED,KAAI,CAAC,eACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,GAAG,0BAA0B,0BAA0B,GAAG,cACnE,CAAC;CAGH,IAAIA,SAAmC;CAEvC,MAAM,EACL,aACA,cACA,UACA,eACA,YACA,SAPmB,MAAM,WAAW,IAAI;CASzC,MAAM,OAAO,IAAI,MAAM;CAEvB,SAAS,gBAAgB,OAAe;EACvC,MAAMC,oBACL,IAAI,QAAQ,QAAQ,YAAY,YAChC,GAAG,IAAI,QAAQ,QAAQ;EACxB,IAAI,MAAM,YAAYA;AACtB,MAAI,IAAI,SAAS,IAAI,CACpB,OAAM,GAAG,IAAI,SAAS;MAEtB,OAAM,GAAG,IAAI,SAAS;AAEvB,QAAM,IAAI,SAAS,IAAI;;CAGxB,IAAI,gBAAgB,eAAe;CACnC,IAAI,mBAAmB,eAAe;CACtC,IAAI,iBAAiB,eAAe;AAEpC,KAAI,eAAe,cAAc;EAChC,MAAM,YAAY,MAAM,YAIrB,eAAe,cAAc;GAC/B,QAAQ;GACR,SAAS,eAAe;GACxB,CAAC;AACF,MAAI,UAAU,MAAM;AACnB,mBAAgB,UAAU,KAAK;AAC/B,sBAAmB,UAAU,KAAK;AAClC,OAAI,CAAC,kBAAkB,UAAU,KAAK,OACrC,kBAAiB,UAAU,KAAK;;;AAKnC,KAAI,gBACH;MAAI,IAAI,MAAM,KACb;OAAI,IAAI,MAAM,QAAQ,gBAAgB;AACrC,QAAI,QAAQ,OAAO,MAAM,yBAAyB;KACjD,UAAU;KACV,UAAU,IAAI,MAAM;KACpB,CAAC;AACF,WAAO,gBAAgB,kBAAkB;;aAEhC,eAAe,yBAAyB;AAClD,OAAI,QAAQ,OAAO,MAAM,kCAAkC,EAC1D,UAAU,gBACV,CAAC;AACF,UAAO,gBAAgB,iBAAiB;;;AAI1C,KAAI;AAEH,MAAI,eAAe,SAClB,UAAS,MAAM,eAAe,SAAS;GACtC;GACA,aAAa,GAAG,IAAI,QAAQ,QAAQ,mBAAmB,eAAe;GACtE,cAAc,eAAe,OAAO,eAAe;GACnD,CAAC;OACI;AAEN,OAAI,CAAC,cACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,sBACnC,CAAC;GAEH,MAAM,mBACL,OAAO,eAAe,mBAAmB,aACtC,eAAe,eAAe,IAAI,GAClC,eAAe;AACnB,YAAS,MAAM,0BAA0B;IACxC,SAAS,eAAe;IACxB;IACA,cAAc,eAAe,OAAO,eAAe;IACnD,aAAa,GAAG,IAAI,QAAQ,QAAQ,mBAAmB,eAAe;IACtE,SAAS;KACR,UAAU,eAAe;KACzB,cAAc,eAAe;KAC7B,aAAa,eAAe;KAC5B;IACD,eAAe;IACf,gBAAgB,eAAe;IAC/B;IACA,CAAC;;UAEK,GAAG;AACX,MAAI,QAAQ,OAAO,MAClB,KAAK,OAAO,MAAM,YAAY,UAAU,IAAK,EAAE,OAAkB,IACjE,EACA;AACD,QAAM,gBAAgB,iCAAiC;;AAExD,KAAI,CAAC,OACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,sBACnC,CAAC;CAEH,MAAMC,WACL,OAAO,eAAe,iBAAiB;EACtC,MAAMC,aACL,eAAe,cACZ,MAAM,eAAe,YAAY,OAAO,GACxC,MAAM,YAAY,QAAQ,iBAAiB;AAE/C,MAAI,CAACA,WACJ,OAAM,gBAAgB,uBAAuB;EAE9C,MAAM,UAAU,eAAe,mBAC5B,MAAM,eAAe,iBAAiBA,WAAS,GAC/CA;EACH,MAAM,QAAQ,QAAQ,QACnB,QAAQ,MAAM,aAAa,GAC3BA,WAAS,OAAO,aAAa;AAChC,MAAI,CAAC,OAAO;AACX,OAAI,QAAQ,OAAO,MAAM,2BAA2BA,WAAS;AAC7D,SAAM,gBAAgB,mBAAmB;;EAE1C,MAAM,KAAK,QAAQ,KAAK,OAAO,QAAQ,GAAG,GAAG,OAAOA,WAAS,GAAG;EAChE,MAAM,OAAO,QAAQ,OAAO,QAAQ,OAAOA,WAAS;AACpD,MAAI,CAAC,MAAM;AACV,OAAI,QAAQ,OAAO,MAAM,2BAA2BA,WAAS;AAC7D,SAAM,gBAAgB,kBAAkB;;AAEzC,SAAO;GACN,GAAGA;GACH,GAAG;GACH;GACA;GACA;GACA;KACE;AACL,KAAI,MAAM;AACT,MACC,IAAI,QAAQ,QAAQ,SAAS,gBAAgB,yBAC5C,QACD,KAAK,MAAM,aAAa,KAAK,SAAS,MAAM,aAAa,CAEzD,QAAO,gBAAgB,sBAAsB;EAE9C,MAAM,kBACL,MAAM,IAAI,QAAQ,gBAAgB,wBACjC,OAAO,SAAS,GAAG,EACnB,eAAe,WACf;AACF,MAAI,iBAAiB;AACpB,OAAI,gBAAgB,WAAW,KAAK,OACnC,QAAO,gBAAgB,2CAA2C;GAEnE,MAAM,aAAa,OAAO,YACzB,OAAO,QAAQ;IACd,aAAa,MAAM,aAAa,OAAO,aAAa,IAAI,QAAQ;IAChE,SAAS,OAAO;IAChB,cAAc,MAAM,aACnB,OAAO,cACP,IAAI,QACJ;IACD,sBAAsB,OAAO;IAC7B,uBAAuB,OAAO;IAC9B,OAAO,OAAO,QAAQ,KAAK,IAAI;IAC/B,CAAC,CAAC,QAAQ,CAAC,GAAG,WAAW,UAAU,OAAU,CAC9C;AACD,SAAM,IAAI,QAAQ,gBAAgB,cACjC,gBAAgB,IAChB,WACA;aAaG,CAXe,MAAM,IAAI,QAAQ,gBAAgB,cAAc;GAClE,QAAQ,KAAK;GACb,YAAY,eAAe;GAC3B,WAAW,SAAS;GACpB,aAAa,MAAM,aAAa,OAAO,aAAa,IAAI,QAAQ;GAChE,sBAAsB,OAAO;GAC7B,uBAAuB,OAAO;GAC9B,OAAO,OAAO,QAAQ,KAAK,IAAI;GAC/B,cAAc,MAAM,aAAa,OAAO,cAAc,IAAI,QAAQ;GAClE,SAAS,OAAO;GAChB,CAAC,CAED,QAAO,gBAAgB,yBAAyB;EAGlD,IAAIC;AACJ,MAAI;AAEH,oBADY,YACO,UAAU;UACtB;AACP,oBAAe;;AAEhB,QAAM,IAAI,SAASC,eAAa;;CAGjC,MAAM,SAAS,MAAM,oBAAoB,KAAK;EAC7C;EACA,SAAS;GACR,YAAY,eAAe;GAC3B,WAAW,SAAS;GACpB,GAAG;GACH,OAAO,OAAO,QAAQ,KAAK,IAAI;GAC/B;EACY;EACb,eACE,eAAe,yBAAyB,CAAC,iBAC1C,eAAe;EAChB,kBAAkB,eAAe;EACjC,CAAC;AAEF,KAAI,OAAO,MACV,QAAO,gBAAgB,OAAO,MAAM,MAAM,IAAI,CAAC,KAAK,IAAI,CAAC;CAE1D,MAAM,EAAE,SAAS,SAAS,OAAO;AACjC,OAAM,iBAAiB,KAAK;EAC3B;EACA;EACA,CAAC;CACF,IAAID;AACJ,KAAI;AAEH,kBADY,OAAO,aAAa,cAAc,cAAc,aACzC,UAAU;SACtB;AACP,iBAAe,OAAO,aACnB,cAAc,cACd;;AAEJ,OAAM,IAAI,SAAS,aAAa;EAEjC;AAEF,MAAM,8BAA8B,EAAE,OAAO;CAC5C,YAAY,EAAE,QAAQ;CAItB,aAAa,EAAE,QAAQ;CAMvB,QAAQ,EACN,MAAM,EAAE,QAAQ,CAAC,CACjB,KAAK,EACL,aAAa,yDACb,CAAC,CACD,UAAU;CAIZ,kBAAkB,EAChB,QAAQ,CACR,KAAK,EACL,aACC,uEACD,CAAC,CACD,UAAU;CACZ,CAAC;;;;;;;;;;;;;;;;AAgBF,MAAa,qBAAqB,YACjC,mBACC,gBACA;CACC,QAAQ;CACR,MAAM;CACN,KAAK,CAAC,kBAAkB;CACxB,UAAU,EACT,SAAS;EACR,aAAa;EACb,WAAW,EACV,OAAO;GACN,aACC;GACD,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY;KACX,KAAK;MACJ,MAAM;MACN,QAAQ;MACR,aACC;MACD;KACD,UAAU;MACT,MAAM;MACN,aACC;MACD,MAAM,CAAC,KAAK;MACZ;KACD;IACD,UAAU,CAAC,OAAO,WAAW;IAC7B,EACD,EACD;GACD,EACD;EACD,EACD;CACD,EACD,OAAO,MAA8B;CACpC,MAAM,UAAU,EAAE,QAAQ;AAC1B,KAAI,CAAC,QACJ,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,0BAA0B,kBACnC,CAAC;CAEH,MAAM,WAAW,QAAQ,OAAO,MAC9B,MAAM,EAAE,eAAe,EAAE,KAAK,WAC/B;AACD,KAAI,CAAC,SACJ,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,iBAAiB,oBAC1B,CAAC;CAEH,MAAM,EACL,YACA,UACA,cACA,aACA,kBACA,cACA,MACA,QACA,QACA,YACA,2BACG;CAEJ,IAAI,eAAe;AACnB,KAAI,CAAC,cAAc;AAClB,MAAI,CAAC,aACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,6BACnC,CAAC;EAEH,MAAM,YAAY,MAAM,YAGrB,cAAc;GAChB,QAAQ;GACR,SAAS,SAAS;GAClB,QAAQ,SAAS;AAChB,MAAE,QAAQ,OAAO,MAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO,EAC5D,cACA,CAAC;;GAEH,CAAC;AACF,MAAI,UAAU,KACb,gBAAe,UAAU,KAAK;;AAIhC,KAAI,CAAC,aACJ,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,0BAA0B,6BACnC,CAAC;CAGH,MAAM,QAAQ,MAAM,cACnB,GACA;EACC,QAAQ,QAAQ,KAAK;EACrB,OAAO,QAAQ,KAAK;EACpB,EACD,OACA;CAED,MAAM,mBACL,OAAO,2BAA2B,aAC/B,uBAAuB,EAAE,GACzB;CAEJ,MAAM,MAAM,MAAM,uBAAuB;EACxC,IAAI;EACJ,SAAS;GACR;GACA;GACA,aACC,eAAe,GAAG,EAAE,QAAQ,QAAQ,mBAAmB;GACxD;EACD,uBAAuB;EACvB,OAAO,MAAM;EACb,cAAc,OAAO,MAAM,eAAe;EAC1C,QAAQ,EAAE,KAAK,UAAU,UAAU,EAAE;EACrC,aACC,eAAe,GAAG,EAAE,QAAQ,QAAQ,mBAAmB;EACxD;EACA;EACA;EACA,CAAC;AAEF,QAAO,EAAE,KAAK;EACb,KAAK,IAAI,UAAU;EACnB,UAAU;EACV,CAAC;EAEH;AAEF,eAAsB,YACrB,QACA,kBACiC;AACjC,KAAI,OAAO,SAAS;EACnB,MAAM,UAAU,UAAU,OAAO,QAAQ;AAOzC,MAAI,SACH;OAAI,QAAQ,OAAO,QAAQ,MAC1B,QAAO;IACN,IAAI,QAAQ;IACZ,eAAe,QAAQ;IACvB,OAAO,QAAQ;IACf,GAAG;IACH;;;AAKJ,KAAI,CAAC,iBACJ,QAAO;CAGR,MAAM,WAAW,MAAM,YAMpB,kBAAkB;EACpB,QAAQ;EACR,SAAS,EACR,eAAe,UAAU,OAAO,eAChC;EACD,CAAC;AACF,QAAO;EACN,IAAI,SAAS,MAAM,OAAO;EAC1B,eAAe,SAAS,MAAM,kBAAkB;EAChD,OAAO,SAAS,MAAM;EACtB,OAAO,SAAS,MAAM;EACtB,MAAM,SAAS,MAAM;EACrB,GAAG,SAAS;EACZ"}
|
|
@@ -20,6 +20,20 @@ interface GenericOAuthConfig {
|
|
|
20
20
|
* If provided, the authorization and token endpoints will be fetched from this URL.
|
|
21
21
|
*/
|
|
22
22
|
discoveryUrl?: string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The expected issuer identifier for validation.
|
|
25
|
+
* If not provided but discoveryUrl is set, it will be fetched from the discovery document.
|
|
26
|
+
* When set, the callback validates that the `iss` parameter matches this value.
|
|
27
|
+
* @see https://datatracker.ietf.org/doc/html/rfc9207
|
|
28
|
+
*/
|
|
29
|
+
issuer?: string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* When true, requires the `iss` parameter in callbacks if an issuer is configured.
|
|
32
|
+
* This provides stricter security but may break with older OAuth servers
|
|
33
|
+
* that don't support issuer identification.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
requireIssuerValidation?: boolean | undefined;
|
|
23
37
|
/**
|
|
24
38
|
* URL for the authorization endpoint.
|
|
25
39
|
* Optional if using discoveryUrl.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _better_auth_core18 from "@better-auth/core";
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/haveibeenpwned/index.d.ts
|
|
4
4
|
interface HaveIBeenPwnedOptions {
|
|
@@ -12,7 +12,7 @@ interface HaveIBeenPwnedOptions {
|
|
|
12
12
|
}
|
|
13
13
|
declare const haveIBeenPwned: (options?: HaveIBeenPwnedOptions | undefined) => {
|
|
14
14
|
id: "haveIBeenPwned";
|
|
15
|
-
init(ctx:
|
|
15
|
+
init(ctx: _better_auth_core18.AuthContext): {
|
|
16
16
|
context: {
|
|
17
17
|
password: {
|
|
18
18
|
hash(password: string): Promise<string>;
|
|
@@ -24,7 +24,7 @@ declare const haveIBeenPwned: (options?: HaveIBeenPwnedOptions | undefined) => {
|
|
|
24
24
|
minPasswordLength: number;
|
|
25
25
|
maxPasswordLength: number;
|
|
26
26
|
};
|
|
27
|
-
checkPassword: (userId: string, ctx:
|
|
27
|
+
checkPassword: (userId: string, ctx: _better_auth_core18.GenericEndpointContext<_better_auth_core18.BetterAuthOptions>) => Promise<boolean>;
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JWKOptions, JWSAlgorithms, Jwk, JwtOptions } from "./types.mjs";
|
|
2
2
|
import { jwt } from "./index.mjs";
|
|
3
3
|
import { JSONWebKeySet } from "jose";
|
|
4
|
-
import * as
|
|
4
|
+
import * as _better_fetch_fetch111 from "@better-fetch/fetch";
|
|
5
5
|
|
|
6
6
|
//#region src/plugins/jwt/client.d.ts
|
|
7
7
|
interface JwtClientOptions {
|
|
@@ -21,7 +21,7 @@ declare const jwtClient: (options?: JwtClientOptions) => {
|
|
|
21
21
|
pathMethods: {
|
|
22
22
|
[x: string]: "GET";
|
|
23
23
|
};
|
|
24
|
-
getActions: ($fetch:
|
|
24
|
+
getActions: ($fetch: _better_fetch_fetch111.BetterFetch) => {
|
|
25
25
|
jwks: (fetchOptions?: any) => Promise<{
|
|
26
26
|
data: null;
|
|
27
27
|
error: {
|
|
@@ -2,8 +2,8 @@ import { JWKOptions, JWSAlgorithms, Jwk, JwtOptions } from "./types.mjs";
|
|
|
2
2
|
import { getJwtToken, signJWT } from "./sign.mjs";
|
|
3
3
|
import { createJwk, generateExportedKeyPair, toExpJWT } from "./utils.mjs";
|
|
4
4
|
import { verifyJWT } from "./verify.mjs";
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
5
|
+
import * as _better_auth_core7 from "@better-auth/core";
|
|
6
|
+
import * as better_call31 from "better-call";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { JSONWebKeySet, JWTPayload } from "jose";
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ declare const jwt: <O extends JwtOptions>(options?: O) => {
|
|
|
12
12
|
id: "jwt";
|
|
13
13
|
options: NoInfer<O>;
|
|
14
14
|
endpoints: {
|
|
15
|
-
getJwks:
|
|
15
|
+
getJwks: better_call31.StrictEndpoint<string, {
|
|
16
16
|
method: "GET";
|
|
17
17
|
metadata: {
|
|
18
18
|
openapi: {
|
|
@@ -89,10 +89,10 @@ declare const jwt: <O extends JwtOptions>(options?: O) => {
|
|
|
89
89
|
};
|
|
90
90
|
};
|
|
91
91
|
}, JSONWebKeySet>;
|
|
92
|
-
getToken:
|
|
92
|
+
getToken: better_call31.StrictEndpoint<"/token", {
|
|
93
93
|
method: "GET";
|
|
94
94
|
requireHeaders: true;
|
|
95
|
-
use: ((inputContext:
|
|
95
|
+
use: ((inputContext: better_call31.MiddlewareInputContext<better_call31.MiddlewareOptions>) => Promise<{
|
|
96
96
|
session: {
|
|
97
97
|
session: Record<string, any> & {
|
|
98
98
|
id: string;
|
|
@@ -141,7 +141,7 @@ declare const jwt: <O extends JwtOptions>(options?: O) => {
|
|
|
141
141
|
}, {
|
|
142
142
|
token: string;
|
|
143
143
|
}>;
|
|
144
|
-
signJWT:
|
|
144
|
+
signJWT: better_call31.StrictEndpoint<string, {
|
|
145
145
|
method: "POST";
|
|
146
146
|
metadata: {
|
|
147
147
|
$Infer: {
|
|
@@ -158,7 +158,7 @@ declare const jwt: <O extends JwtOptions>(options?: O) => {
|
|
|
158
158
|
}, {
|
|
159
159
|
token: string;
|
|
160
160
|
}>;
|
|
161
|
-
verifyJWT:
|
|
161
|
+
verifyJWT: better_call31.StrictEndpoint<string, {
|
|
162
162
|
method: "POST";
|
|
163
163
|
metadata: {
|
|
164
164
|
$Infer: {
|
|
@@ -185,8 +185,8 @@ declare const jwt: <O extends JwtOptions>(options?: O) => {
|
|
|
185
185
|
};
|
|
186
186
|
hooks: {
|
|
187
187
|
after: {
|
|
188
|
-
matcher(context:
|
|
189
|
-
handler: (inputContext:
|
|
188
|
+
matcher(context: _better_auth_core7.HookEndpointContext): boolean;
|
|
189
|
+
handler: (inputContext: better_call31.MiddlewareInputContext<better_call31.MiddlewareOptions>) => Promise<void>;
|
|
190
190
|
}[];
|
|
191
191
|
};
|
|
192
192
|
schema: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _better_auth_core35 from "@better-auth/core";
|
|
2
2
|
import { GenericEndpointContext } from "@better-auth/core";
|
|
3
|
-
import * as
|
|
3
|
+
import * as better_call285 from "better-call";
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/last-login-method/index.d.ts
|
|
6
6
|
/**
|
|
@@ -43,7 +43,7 @@ interface LastLoginMethodOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
declare const lastLoginMethod: <O extends LastLoginMethodOptions>(userConfig?: O | undefined) => {
|
|
45
45
|
id: "last-login-method";
|
|
46
|
-
init(ctx:
|
|
46
|
+
init(ctx: _better_auth_core35.AuthContext): {
|
|
47
47
|
options: {
|
|
48
48
|
databaseHooks: {
|
|
49
49
|
user: {
|
|
@@ -90,7 +90,7 @@ declare const lastLoginMethod: <O extends LastLoginMethodOptions>(userConfig?: O
|
|
|
90
90
|
hooks: {
|
|
91
91
|
after: {
|
|
92
92
|
matcher(): true;
|
|
93
|
-
handler: (inputContext:
|
|
93
|
+
handler: (inputContext: better_call285.MiddlewareInputContext<better_call285.MiddlewareOptions>) => Promise<void>;
|
|
94
94
|
}[];
|
|
95
95
|
};
|
|
96
96
|
schema: O["storeInDatabase"] extends true ? {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Awaitable, GenericEndpointContext } from "@better-auth/core";
|
|
2
|
-
import * as
|
|
2
|
+
import * as better_call39 from "better-call";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/magic-link/index.d.ts
|
|
@@ -68,7 +68,7 @@ declare const magicLink: (options: MagicLinkOptions) => {
|
|
|
68
68
|
*
|
|
69
69
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/sign-in#api-method-sign-in-magic-link)
|
|
70
70
|
*/
|
|
71
|
-
signInMagicLink:
|
|
71
|
+
signInMagicLink: better_call39.StrictEndpoint<"/sign-in/magic-link", {
|
|
72
72
|
method: "POST";
|
|
73
73
|
requireHeaders: true;
|
|
74
74
|
body: z.ZodObject<{
|
|
@@ -119,7 +119,7 @@ declare const magicLink: (options: MagicLinkOptions) => {
|
|
|
119
119
|
*
|
|
120
120
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/magic-link#api-method-magic-link-verify)
|
|
121
121
|
*/
|
|
122
|
-
magicLinkVerify:
|
|
122
|
+
magicLinkVerify: better_call39.StrictEndpoint<"/magic-link/verify", {
|
|
123
123
|
method: "GET";
|
|
124
124
|
query: z.ZodObject<{
|
|
125
125
|
token: z.ZodString;
|
|
@@ -127,7 +127,7 @@ declare const magicLink: (options: MagicLinkOptions) => {
|
|
|
127
127
|
errorCallbackURL: z.ZodOptional<z.ZodString>;
|
|
128
128
|
newUserCallbackURL: z.ZodOptional<z.ZodString>;
|
|
129
129
|
}, z.core.$strip>;
|
|
130
|
-
use: ((inputContext:
|
|
130
|
+
use: ((inputContext: better_call39.MiddlewareInputContext<better_call39.MiddlewareOptions>) => Promise<void>)[];
|
|
131
131
|
requireHeaders: true;
|
|
132
132
|
metadata: {
|
|
133
133
|
openapi: {
|
|
@@ -6,7 +6,7 @@ import { APIError } from "better-call";
|
|
|
6
6
|
|
|
7
7
|
//#region src/plugins/mcp/authorize.ts
|
|
8
8
|
function redirectErrorURL(url, error, description) {
|
|
9
|
-
return `${url.includes("?") ? "&" : "?"}error=${error}&error_description=${description}`;
|
|
9
|
+
return `${url}${url.includes("?") ? "&" : "?"}error=${error}&error_description=${description}`;
|
|
10
10
|
}
|
|
11
11
|
async function authorizeMCPOAuth(ctx, options) {
|
|
12
12
|
ctx.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.mjs","names":["redirectURIWithCode"],"sources":["../../../src/plugins/mcp/authorize.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-call\";\nimport { getSessionFromCtx } from \"../../api\";\nimport { generateRandomString } from \"../../crypto\";\nimport type { OAuthApplication } from \"../oidc-provider/schema\";\nimport type {\n\tAuthorizationQuery,\n\tClient,\n\tOIDCOptions,\n} from \"../oidc-provider/types\";\n\nfunction redirectErrorURL(url: string, error: string, description: string) {\n\treturn `${\n\t\turl.includes(\"?\") ? \"&\" : \"?\"\n\t}error=${error}&error_description=${description}`;\n}\n\nexport async function authorizeMCPOAuth(\n\tctx: GenericEndpointContext,\n\toptions: OIDCOptions,\n) {\n\tctx.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n\tctx.setHeader(\"Access-Control-Allow-Methods\", \"POST, OPTIONS\");\n\tctx.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\");\n\tctx.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\tconst opts = {\n\t\tcodeExpiresIn: 600,\n\t\tdefaultScope: \"openid\",\n\t\t...options,\n\t\tscopes: [\n\t\t\t\"openid\",\n\t\t\t\"profile\",\n\t\t\t\"email\",\n\t\t\t\"offline_access\",\n\t\t\t...(options?.scopes || []),\n\t\t],\n\t};\n\tif (!ctx.request) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"request not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) {\n\t\t/**\n\t\t * If the user is not logged in, we need to redirect them to the\n\t\t * login page.\n\t\t */\n\t\tawait ctx.setSignedCookie(\n\t\t\t\"oidc_login_prompt\",\n\t\t\tJSON.stringify(ctx.query),\n\t\t\tctx.context.secret,\n\t\t\t{\n\t\t\t\tmaxAge: 600,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsameSite: \"lax\",\n\t\t\t},\n\t\t);\n\t\tconst queryFromURL = ctx.request.url?.split(\"?\")[1]!;\n\t\tthrow ctx.redirect(`${options.loginPage}?${queryFromURL}`);\n\t}\n\n\tconst query = ctx.query as AuthorizationQuery;\n\tif (!query.client_id) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=invalid_client`);\n\t}\n\n\tif (!query.response_type) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\t`${ctx.context.baseURL}/error`,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"response_type is required\",\n\t\t\t),\n\t\t);\n\t}\n\n\tconst client = await ctx.context.adapter\n\t\t.findOne<OAuthApplication>({\n\t\t\tmodel: \"oauthApplication\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: ctx.query.client_id,\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\t\t.then((res) => {\n\t\t\tif (!res) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...res,\n\t\t\t\tredirectUrls: res.redirectUrls.split(\",\"),\n\t\t\t\tmetadata: res.metadata ? JSON.parse(res.metadata) : {},\n\t\t\t} as Client;\n\t\t});\n\tif (!client) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=invalid_client`);\n\t}\n\tconst redirectURI = client.redirectUrls.find(\n\t\t(url) => url === ctx.query.redirect_uri,\n\t);\n\n\tif (!redirectURI || !query.redirect_uri) {\n\t\t/**\n\t\t * show UI error here warning the user that the redirect URI is invalid\n\t\t */\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Invalid redirect URI\",\n\t\t});\n\t}\n\tif (client.disabled) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=client_disabled`);\n\t}\n\n\tif (query.response_type !== \"code\") {\n\t\tthrow ctx.redirect(\n\t\t\t`${ctx.context.baseURL}/error?error=unsupported_response_type`,\n\t\t);\n\t}\n\n\tconst requestScope =\n\t\tquery.scope?.split(\" \").filter((s) => s) || opts.defaultScope.split(\" \");\n\tconst invalidScopes = requestScope.filter((scope) => {\n\t\treturn !opts.scopes.includes(scope);\n\t});\n\tif (invalidScopes.length) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_scope\",\n\t\t\t\t`The following scopes are invalid: ${invalidScopes.join(\", \")}`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (\n\t\t(!query.code_challenge || !query.code_challenge_method) &&\n\t\toptions.requirePKCE\n\t) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"pkce is required\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!query.code_challenge_method) {\n\t\tquery.code_challenge_method = \"plain\";\n\t}\n\n\tif (\n\t\t![\n\t\t\t\"s256\",\n\t\t\toptions.allowPlainCodeChallengeMethod ? \"plain\" : \"s256\",\n\t\t].includes(query.code_challenge_method?.toLowerCase() || \"\")\n\t) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"invalid code_challenge method\",\n\t\t\t),\n\t\t);\n\t}\n\n\tconst code = generateRandomString(32, \"a-z\", \"A-Z\", \"0-9\");\n\tconst codeExpiresInMs = opts.codeExpiresIn * 1000;\n\tconst expiresAt = new Date(Date.now() + codeExpiresInMs);\n\ttry {\n\t\t/**\n\t\t * Save the code in the database\n\t\t */\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: JSON.stringify({\n\t\t\t\tclientId: client.clientId,\n\t\t\t\tredirectURI: query.redirect_uri,\n\t\t\t\tscope: requestScope,\n\t\t\t\tuserId: session.user.id,\n\t\t\t\tauthTime: new Date(session.session.createdAt).getTime(),\n\t\t\t\t/**\n\t\t\t\t * If the prompt is set to `consent`, then we need\n\t\t\t\t * to require the user to consent to the scopes.\n\t\t\t\t *\n\t\t\t\t * This means the code now needs to be treated as a\n\t\t\t\t * consent request.\n\t\t\t\t *\n\t\t\t\t * once the user consents, the code will be updated\n\t\t\t\t * with the actual code. This is to prevent the\n\t\t\t\t * client from using the code before the user\n\t\t\t\t * consents.\n\t\t\t\t */\n\t\t\t\trequireConsent: query.prompt === \"consent\",\n\t\t\t\tstate: query.prompt === \"consent\" ? query.state : null,\n\t\t\t\tcodeChallenge: query.code_challenge,\n\t\t\t\tcodeChallengeMethod: query.code_challenge_method,\n\t\t\t\tnonce: query.nonce,\n\t\t\t}),\n\t\t\tidentifier: code,\n\t\t\texpiresAt,\n\t\t});\n\t} catch {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"server_error\",\n\t\t\t\t\"An error occurred while processing the request\",\n\t\t\t),\n\t\t);\n\t}\n\n\t// Consent is NOT required - redirect with the code immediately\n\tif (query.prompt !== \"consent\") {\n\t\tconst redirectURIWithCode = new URL(redirectURI);\n\t\tredirectURIWithCode.searchParams.set(\"code\", code);\n\t\tif (ctx.query.state) {\n\t\t\tredirectURIWithCode.searchParams.set(\"state\", ctx.query.state);\n\t\t}\n\t\tthrow ctx.redirect(redirectURIWithCode.toString());\n\t}\n\n\t// Consent is REQUIRED - redirect to consent page or show consent HTML\n\tif (options?.consentPage) {\n\t\t// Set cookie to support cookie-based consent flows\n\t\tawait ctx.setSignedCookie(\"oidc_consent_prompt\", code, ctx.context.secret, {\n\t\t\tmaxAge: 600,\n\t\t\tpath: \"/\",\n\t\t\tsameSite: \"lax\",\n\t\t});\n\n\t\t// Pass the consent code as a URL parameter to support URL-BASED consent flows\n\t\tconst urlParams = new URLSearchParams();\n\t\turlParams.set(\"consent_code\", code);\n\t\turlParams.set(\"client_id\", client.clientId);\n\t\turlParams.set(\"scope\", requestScope.join(\" \"));\n\t\tconst consentURI = `${options.consentPage}?${urlParams.toString()}`;\n\n\t\tthrow ctx.redirect(consentURI);\n\t}\n\n\t// No consent page configured - fall back to direct redirect with code\n\tconst redirectURIWithCode = new URL(redirectURI);\n\tredirectURIWithCode.searchParams.set(\"code\", code);\n\tif (ctx.query.state) {\n\t\tredirectURIWithCode.searchParams.set(\"state\", ctx.query.state);\n\t}\n\tthrow ctx.redirect(redirectURIWithCode.toString());\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"authorize.mjs","names":["redirectURIWithCode"],"sources":["../../../src/plugins/mcp/authorize.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-call\";\nimport { getSessionFromCtx } from \"../../api\";\nimport { generateRandomString } from \"../../crypto\";\nimport type { OAuthApplication } from \"../oidc-provider/schema\";\nimport type {\n\tAuthorizationQuery,\n\tClient,\n\tOIDCOptions,\n} from \"../oidc-provider/types\";\n\nfunction redirectErrorURL(url: string, error: string, description: string) {\n\treturn `${url}${\n\t\turl.includes(\"?\") ? \"&\" : \"?\"\n\t}error=${error}&error_description=${description}`;\n}\n\nexport async function authorizeMCPOAuth(\n\tctx: GenericEndpointContext,\n\toptions: OIDCOptions,\n) {\n\tctx.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n\tctx.setHeader(\"Access-Control-Allow-Methods\", \"POST, OPTIONS\");\n\tctx.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\");\n\tctx.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\tconst opts = {\n\t\tcodeExpiresIn: 600,\n\t\tdefaultScope: \"openid\",\n\t\t...options,\n\t\tscopes: [\n\t\t\t\"openid\",\n\t\t\t\"profile\",\n\t\t\t\"email\",\n\t\t\t\"offline_access\",\n\t\t\t...(options?.scopes || []),\n\t\t],\n\t};\n\tif (!ctx.request) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"request not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) {\n\t\t/**\n\t\t * If the user is not logged in, we need to redirect them to the\n\t\t * login page.\n\t\t */\n\t\tawait ctx.setSignedCookie(\n\t\t\t\"oidc_login_prompt\",\n\t\t\tJSON.stringify(ctx.query),\n\t\t\tctx.context.secret,\n\t\t\t{\n\t\t\t\tmaxAge: 600,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsameSite: \"lax\",\n\t\t\t},\n\t\t);\n\t\tconst queryFromURL = ctx.request.url?.split(\"?\")[1]!;\n\t\tthrow ctx.redirect(`${options.loginPage}?${queryFromURL}`);\n\t}\n\n\tconst query = ctx.query as AuthorizationQuery;\n\tif (!query.client_id) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=invalid_client`);\n\t}\n\n\tif (!query.response_type) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\t`${ctx.context.baseURL}/error`,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"response_type is required\",\n\t\t\t),\n\t\t);\n\t}\n\n\tconst client = await ctx.context.adapter\n\t\t.findOne<OAuthApplication>({\n\t\t\tmodel: \"oauthApplication\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: ctx.query.client_id,\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\t\t.then((res) => {\n\t\t\tif (!res) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...res,\n\t\t\t\tredirectUrls: res.redirectUrls.split(\",\"),\n\t\t\t\tmetadata: res.metadata ? JSON.parse(res.metadata) : {},\n\t\t\t} as Client;\n\t\t});\n\tif (!client) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=invalid_client`);\n\t}\n\tconst redirectURI = client.redirectUrls.find(\n\t\t(url) => url === ctx.query.redirect_uri,\n\t);\n\n\tif (!redirectURI || !query.redirect_uri) {\n\t\t/**\n\t\t * show UI error here warning the user that the redirect URI is invalid\n\t\t */\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Invalid redirect URI\",\n\t\t});\n\t}\n\tif (client.disabled) {\n\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=client_disabled`);\n\t}\n\n\tif (query.response_type !== \"code\") {\n\t\tthrow ctx.redirect(\n\t\t\t`${ctx.context.baseURL}/error?error=unsupported_response_type`,\n\t\t);\n\t}\n\n\tconst requestScope =\n\t\tquery.scope?.split(\" \").filter((s) => s) || opts.defaultScope.split(\" \");\n\tconst invalidScopes = requestScope.filter((scope) => {\n\t\treturn !opts.scopes.includes(scope);\n\t});\n\tif (invalidScopes.length) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_scope\",\n\t\t\t\t`The following scopes are invalid: ${invalidScopes.join(\", \")}`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (\n\t\t(!query.code_challenge || !query.code_challenge_method) &&\n\t\toptions.requirePKCE\n\t) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"pkce is required\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!query.code_challenge_method) {\n\t\tquery.code_challenge_method = \"plain\";\n\t}\n\n\tif (\n\t\t![\n\t\t\t\"s256\",\n\t\t\toptions.allowPlainCodeChallengeMethod ? \"plain\" : \"s256\",\n\t\t].includes(query.code_challenge_method?.toLowerCase() || \"\")\n\t) {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"invalid code_challenge method\",\n\t\t\t),\n\t\t);\n\t}\n\n\tconst code = generateRandomString(32, \"a-z\", \"A-Z\", \"0-9\");\n\tconst codeExpiresInMs = opts.codeExpiresIn * 1000;\n\tconst expiresAt = new Date(Date.now() + codeExpiresInMs);\n\ttry {\n\t\t/**\n\t\t * Save the code in the database\n\t\t */\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: JSON.stringify({\n\t\t\t\tclientId: client.clientId,\n\t\t\t\tredirectURI: query.redirect_uri,\n\t\t\t\tscope: requestScope,\n\t\t\t\tuserId: session.user.id,\n\t\t\t\tauthTime: new Date(session.session.createdAt).getTime(),\n\t\t\t\t/**\n\t\t\t\t * If the prompt is set to `consent`, then we need\n\t\t\t\t * to require the user to consent to the scopes.\n\t\t\t\t *\n\t\t\t\t * This means the code now needs to be treated as a\n\t\t\t\t * consent request.\n\t\t\t\t *\n\t\t\t\t * once the user consents, the code will be updated\n\t\t\t\t * with the actual code. This is to prevent the\n\t\t\t\t * client from using the code before the user\n\t\t\t\t * consents.\n\t\t\t\t */\n\t\t\t\trequireConsent: query.prompt === \"consent\",\n\t\t\t\tstate: query.prompt === \"consent\" ? query.state : null,\n\t\t\t\tcodeChallenge: query.code_challenge,\n\t\t\t\tcodeChallengeMethod: query.code_challenge_method,\n\t\t\t\tnonce: query.nonce,\n\t\t\t}),\n\t\t\tidentifier: code,\n\t\t\texpiresAt,\n\t\t});\n\t} catch {\n\t\tthrow ctx.redirect(\n\t\t\tredirectErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"server_error\",\n\t\t\t\t\"An error occurred while processing the request\",\n\t\t\t),\n\t\t);\n\t}\n\n\t// Consent is NOT required - redirect with the code immediately\n\tif (query.prompt !== \"consent\") {\n\t\tconst redirectURIWithCode = new URL(redirectURI);\n\t\tredirectURIWithCode.searchParams.set(\"code\", code);\n\t\tif (ctx.query.state) {\n\t\t\tredirectURIWithCode.searchParams.set(\"state\", ctx.query.state);\n\t\t}\n\t\tthrow ctx.redirect(redirectURIWithCode.toString());\n\t}\n\n\t// Consent is REQUIRED - redirect to consent page or show consent HTML\n\tif (options?.consentPage) {\n\t\t// Set cookie to support cookie-based consent flows\n\t\tawait ctx.setSignedCookie(\"oidc_consent_prompt\", code, ctx.context.secret, {\n\t\t\tmaxAge: 600,\n\t\t\tpath: \"/\",\n\t\t\tsameSite: \"lax\",\n\t\t});\n\n\t\t// Pass the consent code as a URL parameter to support URL-BASED consent flows\n\t\tconst urlParams = new URLSearchParams();\n\t\turlParams.set(\"consent_code\", code);\n\t\turlParams.set(\"client_id\", client.clientId);\n\t\turlParams.set(\"scope\", requestScope.join(\" \"));\n\t\tconst consentURI = `${options.consentPage}?${urlParams.toString()}`;\n\n\t\tthrow ctx.redirect(consentURI);\n\t}\n\n\t// No consent page configured - fall back to direct redirect with code\n\tconst redirectURIWithCode = new URL(redirectURI);\n\tredirectURIWithCode.searchParams.set(\"code\", code);\n\tif (ctx.query.state) {\n\t\tredirectURIWithCode.searchParams.set(\"state\", ctx.query.state);\n\t}\n\tthrow ctx.redirect(redirectURIWithCode.toString());\n}\n"],"mappings":";;;;;;;AAWA,SAAS,iBAAiB,KAAa,OAAe,aAAqB;AAC1E,QAAO,GAAG,MACT,IAAI,SAAS,IAAI,GAAG,MAAM,IAC1B,QAAQ,MAAM,qBAAqB;;AAGrC,eAAsB,kBACrB,KACA,SACC;AACD,KAAI,UAAU,+BAA+B,IAAI;AACjD,KAAI,UAAU,gCAAgC,gBAAgB;AAC9D,KAAI,UAAU,gCAAgC,8BAA8B;AAC5E,KAAI,UAAU,0BAA0B,QAAQ;CAChD,MAAM,OAAO;EACZ,eAAe;EACf,cAAc;EACd,GAAG;EACH,QAAQ;GACP;GACA;GACA;GACA;GACA,GAAI,SAAS,UAAU,EAAE;GACzB;EACD;AACD,KAAI,CAAC,IAAI,QACR,OAAM,IAAI,SAAS,gBAAgB;EAClC,mBAAmB;EACnB,OAAO;EACP,CAAC;CAEH,MAAM,UAAU,MAAM,kBAAkB,IAAI;AAC5C,KAAI,CAAC,SAAS;;;;;AAKb,QAAM,IAAI,gBACT,qBACA,KAAK,UAAU,IAAI,MAAM,EACzB,IAAI,QAAQ,QACZ;GACC,QAAQ;GACR,MAAM;GACN,UAAU;GACV,CACD;EACD,MAAM,eAAe,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC;AACjD,QAAM,IAAI,SAAS,GAAG,QAAQ,UAAU,GAAG,eAAe;;CAG3D,MAAM,QAAQ,IAAI;AAClB,KAAI,CAAC,MAAM,UACV,OAAM,IAAI,SAAS,GAAG,IAAI,QAAQ,QAAQ,6BAA6B;AAGxE,KAAI,CAAC,MAAM,cACV,OAAM,IAAI,SACT,iBACC,GAAG,IAAI,QAAQ,QAAQ,SACvB,mBACA,4BACA,CACD;CAGF,MAAM,SAAS,MAAM,IAAI,QAAQ,QAC/B,QAA0B;EAC1B,OAAO;EACP,OAAO,CACN;GACC,OAAO;GACP,OAAO,IAAI,MAAM;GACjB,CACD;EACD,CAAC,CACD,MAAM,QAAQ;AACd,MAAI,CAAC,IACJ,QAAO;AAER,SAAO;GACN,GAAG;GACH,cAAc,IAAI,aAAa,MAAM,IAAI;GACzC,UAAU,IAAI,WAAW,KAAK,MAAM,IAAI,SAAS,GAAG,EAAE;GACtD;GACA;AACH,KAAI,CAAC,OACJ,OAAM,IAAI,SAAS,GAAG,IAAI,QAAQ,QAAQ,6BAA6B;CAExE,MAAM,cAAc,OAAO,aAAa,MACtC,QAAQ,QAAQ,IAAI,MAAM,aAC3B;AAED,KAAI,CAAC,eAAe,CAAC,MAAM;;;;AAI1B,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,wBACT,CAAC;AAEH,KAAI,OAAO,SACV,OAAM,IAAI,SAAS,GAAG,IAAI,QAAQ,QAAQ,8BAA8B;AAGzE,KAAI,MAAM,kBAAkB,OAC3B,OAAM,IAAI,SACT,GAAG,IAAI,QAAQ,QAAQ,wCACvB;CAGF,MAAM,eACL,MAAM,OAAO,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,IAAI,KAAK,aAAa,MAAM,IAAI;CACzE,MAAM,gBAAgB,aAAa,QAAQ,UAAU;AACpD,SAAO,CAAC,KAAK,OAAO,SAAS,MAAM;GAClC;AACF,KAAI,cAAc,OACjB,OAAM,IAAI,SACT,iBACC,MAAM,cACN,iBACA,qCAAqC,cAAc,KAAK,KAAK,GAC7D,CACD;AAGF,MACE,CAAC,MAAM,kBAAkB,CAAC,MAAM,0BACjC,QAAQ,YAER,OAAM,IAAI,SACT,iBACC,MAAM,cACN,mBACA,mBACA,CACD;AAGF,KAAI,CAAC,MAAM,sBACV,OAAM,wBAAwB;AAG/B,KACC,CAAC,CACA,QACA,QAAQ,gCAAgC,UAAU,OAClD,CAAC,SAAS,MAAM,uBAAuB,aAAa,IAAI,GAAG,CAE5D,OAAM,IAAI,SACT,iBACC,MAAM,cACN,mBACA,gCACA,CACD;CAGF,MAAM,OAAO,qBAAqB,IAAI,OAAO,OAAO,MAAM;CAC1D,MAAM,kBAAkB,KAAK,gBAAgB;CAC7C,MAAM,YAAY,IAAI,KAAK,KAAK,KAAK,GAAG,gBAAgB;AACxD,KAAI;;;;AAIH,QAAM,IAAI,QAAQ,gBAAgB,wBAAwB;GACzD,OAAO,KAAK,UAAU;IACrB,UAAU,OAAO;IACjB,aAAa,MAAM;IACnB,OAAO;IACP,QAAQ,QAAQ,KAAK;IACrB,UAAU,IAAI,KAAK,QAAQ,QAAQ,UAAU,CAAC,SAAS;IAavD,gBAAgB,MAAM,WAAW;IACjC,OAAO,MAAM,WAAW,YAAY,MAAM,QAAQ;IAClD,eAAe,MAAM;IACrB,qBAAqB,MAAM;IAC3B,OAAO,MAAM;IACb,CAAC;GACF,YAAY;GACZ;GACA,CAAC;SACK;AACP,QAAM,IAAI,SACT,iBACC,MAAM,cACN,gBACA,iDACA,CACD;;AAIF,KAAI,MAAM,WAAW,WAAW;EAC/B,MAAMA,wBAAsB,IAAI,IAAI,YAAY;AAChD,wBAAoB,aAAa,IAAI,QAAQ,KAAK;AAClD,MAAI,IAAI,MAAM,MACb,uBAAoB,aAAa,IAAI,SAAS,IAAI,MAAM,MAAM;AAE/D,QAAM,IAAI,SAASA,sBAAoB,UAAU,CAAC;;AAInD,KAAI,SAAS,aAAa;AAEzB,QAAM,IAAI,gBAAgB,uBAAuB,MAAM,IAAI,QAAQ,QAAQ;GAC1E,QAAQ;GACR,MAAM;GACN,UAAU;GACV,CAAC;EAGF,MAAM,YAAY,IAAI,iBAAiB;AACvC,YAAU,IAAI,gBAAgB,KAAK;AACnC,YAAU,IAAI,aAAa,OAAO,SAAS;AAC3C,YAAU,IAAI,SAAS,aAAa,KAAK,IAAI,CAAC;EAC9C,MAAM,aAAa,GAAG,QAAQ,YAAY,GAAG,UAAU,UAAU;AAEjE,QAAM,IAAI,SAAS,WAAW;;CAI/B,MAAM,sBAAsB,IAAI,IAAI,YAAY;AAChD,qBAAoB,aAAa,IAAI,QAAQ,KAAK;AAClD,KAAI,IAAI,MAAM,MACb,qBAAoB,aAAa,IAAI,SAAS,IAAI,MAAM,MAAM;AAE/D,OAAM,IAAI,SAAS,oBAAoB,UAAU,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OAuthAccessToken, OIDCMetadata, OIDCOptions } from "../oidc-provider/types.mjs";
|
|
2
2
|
import "../oidc-provider/index.mjs";
|
|
3
3
|
import { BetterAuthOptions, GenericEndpointContext } from "@better-auth/core";
|
|
4
|
-
import * as
|
|
4
|
+
import * as better_call287 from "better-call";
|
|
5
5
|
import * as z from "zod";
|
|
6
6
|
|
|
7
7
|
//#region src/plugins/mcp/index.d.ts
|
|
@@ -24,18 +24,18 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
24
24
|
hooks: {
|
|
25
25
|
after: {
|
|
26
26
|
matcher(): true;
|
|
27
|
-
handler: (inputContext:
|
|
27
|
+
handler: (inputContext: better_call287.MiddlewareInputContext<better_call287.MiddlewareOptions>) => Promise<void>;
|
|
28
28
|
}[];
|
|
29
29
|
};
|
|
30
30
|
endpoints: {
|
|
31
|
-
oAuthConsent:
|
|
31
|
+
oAuthConsent: better_call287.StrictEndpoint<"/oauth2/consent", {
|
|
32
32
|
method: "POST";
|
|
33
33
|
operationId: string;
|
|
34
34
|
body: z.ZodObject<{
|
|
35
35
|
accept: z.ZodBoolean;
|
|
36
36
|
consent_code: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodString>>>;
|
|
37
37
|
}, z.core.$strip>;
|
|
38
|
-
use: ((inputContext:
|
|
38
|
+
use: ((inputContext: better_call287.MiddlewareInputContext<better_call287.MiddlewareOptions>) => Promise<{
|
|
39
39
|
session: {
|
|
40
40
|
session: Record<string, any> & {
|
|
41
41
|
id: string;
|
|
@@ -107,13 +107,13 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
107
107
|
}, {
|
|
108
108
|
redirectURI: string;
|
|
109
109
|
}>;
|
|
110
|
-
getMcpOAuthConfig:
|
|
110
|
+
getMcpOAuthConfig: better_call287.StrictEndpoint<"/.well-known/oauth-authorization-server", {
|
|
111
111
|
method: "GET";
|
|
112
112
|
metadata: {
|
|
113
113
|
readonly scope: "server";
|
|
114
114
|
};
|
|
115
115
|
}, OIDCMetadata | null>;
|
|
116
|
-
getMCPProtectedResource:
|
|
116
|
+
getMCPProtectedResource: better_call287.StrictEndpoint<"/.well-known/oauth-protected-resource", {
|
|
117
117
|
method: "GET";
|
|
118
118
|
metadata: {
|
|
119
119
|
readonly scope: "server";
|
|
@@ -126,7 +126,7 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
126
126
|
bearer_methods_supported: string[];
|
|
127
127
|
resource_signing_alg_values_supported: string[];
|
|
128
128
|
}>;
|
|
129
|
-
mcpOAuthAuthorize:
|
|
129
|
+
mcpOAuthAuthorize: better_call287.StrictEndpoint<"/mcp/authorize", {
|
|
130
130
|
method: "GET";
|
|
131
131
|
query: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
132
132
|
metadata: {
|
|
@@ -149,7 +149,7 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
149
149
|
};
|
|
150
150
|
};
|
|
151
151
|
}, void>;
|
|
152
|
-
mcpOAuthToken:
|
|
152
|
+
mcpOAuthToken: better_call287.StrictEndpoint<"/mcp/token", {
|
|
153
153
|
method: "POST";
|
|
154
154
|
body: z.ZodRecord<z.ZodAny, z.ZodAny>;
|
|
155
155
|
metadata: {
|
|
@@ -170,7 +170,7 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
170
170
|
scope: string;
|
|
171
171
|
id_token: string | undefined;
|
|
172
172
|
}>;
|
|
173
|
-
registerMcpClient:
|
|
173
|
+
registerMcpClient: better_call287.StrictEndpoint<"/mcp/register", {
|
|
174
174
|
method: "POST";
|
|
175
175
|
body: z.ZodObject<{
|
|
176
176
|
redirect_uris: z.ZodArray<z.ZodString>;
|
|
@@ -288,7 +288,7 @@ declare const mcp: (options: MCPOptions) => {
|
|
|
288
288
|
};
|
|
289
289
|
};
|
|
290
290
|
}, Response>;
|
|
291
|
-
getMcpSession:
|
|
291
|
+
getMcpSession: better_call287.StrictEndpoint<"/mcp/get-session", {
|
|
292
292
|
method: "GET";
|
|
293
293
|
requireHeaders: true;
|
|
294
294
|
}, OAuthAccessToken | null>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
1
|
+
import * as _better_auth_core8 from "@better-auth/core";
|
|
2
|
+
import * as better_call43 from "better-call";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/multi-session/index.d.ts
|
|
@@ -29,7 +29,7 @@ declare const multiSession: (options?: MultiSessionConfig | undefined) => {
|
|
|
29
29
|
*
|
|
30
30
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/multi-session#api-method-multi-session-list-device-sessions)
|
|
31
31
|
*/
|
|
32
|
-
listDeviceSessions:
|
|
32
|
+
listDeviceSessions: better_call43.StrictEndpoint<"/multi-session/list-device-sessions", {
|
|
33
33
|
method: "GET";
|
|
34
34
|
requireHeaders: true;
|
|
35
35
|
}, {
|
|
@@ -68,13 +68,13 @@ declare const multiSession: (options?: MultiSessionConfig | undefined) => {
|
|
|
68
68
|
*
|
|
69
69
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/multi-session#api-method-multi-session-set-active)
|
|
70
70
|
*/
|
|
71
|
-
setActiveSession:
|
|
71
|
+
setActiveSession: better_call43.StrictEndpoint<"/multi-session/set-active", {
|
|
72
72
|
method: "POST";
|
|
73
73
|
body: z.ZodObject<{
|
|
74
74
|
sessionToken: z.ZodString;
|
|
75
75
|
}, z.core.$strip>;
|
|
76
76
|
requireHeaders: true;
|
|
77
|
-
use: ((inputContext:
|
|
77
|
+
use: ((inputContext: better_call43.MiddlewareInputContext<better_call43.MiddlewareOptions>) => Promise<{
|
|
78
78
|
session: {
|
|
79
79
|
session: Record<string, any> & {
|
|
80
80
|
id: string;
|
|
@@ -155,13 +155,13 @@ declare const multiSession: (options?: MultiSessionConfig | undefined) => {
|
|
|
155
155
|
*
|
|
156
156
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/multi-session#api-method-multi-session-revoke)
|
|
157
157
|
*/
|
|
158
|
-
revokeDeviceSession:
|
|
158
|
+
revokeDeviceSession: better_call43.StrictEndpoint<"/multi-session/revoke", {
|
|
159
159
|
method: "POST";
|
|
160
160
|
body: z.ZodObject<{
|
|
161
161
|
sessionToken: z.ZodString;
|
|
162
162
|
}, z.core.$strip>;
|
|
163
163
|
requireHeaders: true;
|
|
164
|
-
use: ((inputContext:
|
|
164
|
+
use: ((inputContext: better_call43.MiddlewareInputContext<better_call43.MiddlewareOptions>) => Promise<{
|
|
165
165
|
session: {
|
|
166
166
|
session: Record<string, any> & {
|
|
167
167
|
id: string;
|
|
@@ -212,8 +212,8 @@ declare const multiSession: (options?: MultiSessionConfig | undefined) => {
|
|
|
212
212
|
};
|
|
213
213
|
hooks: {
|
|
214
214
|
after: {
|
|
215
|
-
matcher: (context:
|
|
216
|
-
handler: (inputContext:
|
|
215
|
+
matcher: (context: _better_auth_core8.HookEndpointContext) => boolean;
|
|
216
|
+
handler: (inputContext: better_call43.MiddlewareInputContext<better_call43.MiddlewareOptions>) => Promise<void>;
|
|
217
217
|
}[];
|
|
218
218
|
};
|
|
219
219
|
options: MultiSessionConfig | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
1
|
+
import * as _better_auth_core10 from "@better-auth/core";
|
|
2
|
+
import * as better_call212 from "better-call";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/oauth-proxy/index.d.ts
|
|
@@ -34,14 +34,14 @@ declare const oAuthProxy: <O extends OAuthProxyOptions>(opts?: O) => {
|
|
|
34
34
|
id: "oauth-proxy";
|
|
35
35
|
options: NoInfer<O>;
|
|
36
36
|
endpoints: {
|
|
37
|
-
oAuthProxy:
|
|
37
|
+
oAuthProxy: better_call212.StrictEndpoint<"/oauth-proxy-callback", {
|
|
38
38
|
method: "GET";
|
|
39
39
|
operationId: string;
|
|
40
40
|
query: z.ZodObject<{
|
|
41
41
|
callbackURL: z.ZodString;
|
|
42
42
|
cookies: z.ZodString;
|
|
43
43
|
}, z.core.$strip>;
|
|
44
|
-
use: ((inputContext:
|
|
44
|
+
use: ((inputContext: better_call212.MiddlewareInputContext<better_call212.MiddlewareOptions>) => Promise<void>)[];
|
|
45
45
|
metadata: {
|
|
46
46
|
openapi: {
|
|
47
47
|
operationId: string;
|
|
@@ -71,12 +71,12 @@ declare const oAuthProxy: <O extends OAuthProxyOptions>(opts?: O) => {
|
|
|
71
71
|
};
|
|
72
72
|
hooks: {
|
|
73
73
|
before: {
|
|
74
|
-
matcher(context:
|
|
75
|
-
handler: (inputContext:
|
|
74
|
+
matcher(context: _better_auth_core10.HookEndpointContext): boolean;
|
|
75
|
+
handler: (inputContext: better_call212.MiddlewareInputContext<better_call212.MiddlewareOptions>) => Promise<void>;
|
|
76
76
|
}[];
|
|
77
77
|
after: {
|
|
78
|
-
matcher(context:
|
|
79
|
-
handler: (inputContext:
|
|
78
|
+
matcher(context: _better_auth_core10.HookEndpointContext): boolean;
|
|
79
|
+
handler: (inputContext: better_call212.MiddlewareInputContext<better_call212.MiddlewareOptions>) => Promise<void>;
|
|
80
80
|
}[];
|
|
81
81
|
};
|
|
82
82
|
};
|
|
@@ -8,7 +8,7 @@ import { APIError } from "better-call";
|
|
|
8
8
|
|
|
9
9
|
//#region src/plugins/oidc-provider/authorize.ts
|
|
10
10
|
function formatErrorURL(url, error, description) {
|
|
11
|
-
return `${url.includes("?") ? "&" : "?"}error=${error}&error_description=${description}`;
|
|
11
|
+
return `${url}${url.includes("?") ? "&" : "?"}error=${error}&error_description=${description}`;
|
|
12
12
|
}
|
|
13
13
|
function getErrorURL(ctx, error, description) {
|
|
14
14
|
return formatErrorURL(ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`, error, description);
|