better-auth 1.4.9 → 1.5.0-beta.1
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/api/index.d.mts +396 -395
- package/dist/api/index.mjs +6 -4
- package/dist/api/index.mjs.map +1 -1
- package/dist/api/middlewares/origin-check.d.mts +3 -3
- package/dist/api/middlewares/origin-check.mjs +14 -4
- package/dist/api/middlewares/origin-check.mjs.map +1 -1
- package/dist/api/routes/account.d.mts +11 -11
- package/dist/api/routes/account.mjs +59 -30
- package/dist/api/routes/account.mjs.map +1 -1
- package/dist/api/routes/callback.d.mts +2 -2
- package/dist/api/routes/email-verification.d.mts +4 -4
- package/dist/api/routes/email-verification.mjs +14 -14
- 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/reset-password.d.mts +5 -5
- package/dist/api/routes/reset-password.mjs +9 -7
- package/dist/api/routes/reset-password.mjs.map +1 -1
- package/dist/api/routes/session.d.mts +14 -14
- package/dist/api/routes/session.mjs +31 -11
- package/dist/api/routes/session.mjs.map +1 -1
- package/dist/api/routes/sign-in.d.mts +3 -3
- package/dist/api/routes/sign-in.mjs +22 -17
- package/dist/api/routes/sign-in.mjs.map +1 -1
- package/dist/api/routes/sign-out.d.mts +2 -2
- package/dist/api/routes/sign-up.d.mts +2 -2
- package/dist/api/routes/sign-up.mjs +15 -12
- package/dist/api/routes/sign-up.mjs.map +1 -1
- package/dist/api/routes/update-user.d.mts +13 -13
- package/dist/api/routes/update-user.mjs +29 -24
- package/dist/api/routes/update-user.mjs.map +1 -1
- package/dist/api/to-auth-endpoints.mjs +7 -6
- package/dist/api/to-auth-endpoints.mjs.map +1 -1
- package/dist/client/lynx/index.d.mts +15 -15
- package/dist/client/plugins/index.d.mts +12 -2
- package/dist/client/plugins/index.mjs +11 -1
- package/dist/client/react/index.d.mts +13 -13
- package/dist/client/solid/index.d.mts +13 -13
- package/dist/client/svelte/index.d.mts +15 -15
- package/dist/client/types.d.mts +4 -1
- package/dist/client/vue/index.d.mts +13 -13
- package/dist/context/create-context.mjs +2 -2
- package/dist/context/create-context.mjs.map +1 -1
- package/dist/context/helpers.mjs +2 -2
- package/dist/context/helpers.mjs.map +1 -1
- package/dist/db/field.d.mts +6 -6
- package/dist/db/schema.mjs +14 -5
- package/dist/db/schema.mjs.map +1 -1
- package/dist/index.d.mts +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.d.mts +4 -4
- package/dist/oauth2/link-account.mjs +3 -2
- package/dist/oauth2/link-account.mjs.map +1 -1
- package/dist/oauth2/state.mjs +3 -3
- package/dist/oauth2/state.mjs.map +1 -1
- package/dist/plugins/admin/admin.d.mts +200 -137
- package/dist/plugins/admin/admin.mjs +3 -4
- package/dist/plugins/admin/admin.mjs.map +1 -1
- package/dist/plugins/admin/client.d.mts +87 -0
- package/dist/plugins/admin/client.mjs +3 -1
- package/dist/plugins/admin/client.mjs.map +1 -1
- package/dist/plugins/admin/error-codes.d.mts +90 -0
- package/dist/plugins/admin/error-codes.mjs.map +1 -1
- package/dist/plugins/admin/routes.mjs +40 -46
- package/dist/plugins/admin/routes.mjs.map +1 -1
- package/dist/plugins/anonymous/client.d.mts +19 -0
- package/dist/plugins/anonymous/client.mjs +4 -1
- package/dist/plugins/anonymous/client.mjs.map +1 -1
- package/dist/plugins/anonymous/error-codes.d.mts +22 -0
- package/dist/plugins/anonymous/index.d.mts +21 -9
- package/dist/plugins/anonymous/index.mjs +5 -5
- package/dist/plugins/anonymous/index.mjs.map +1 -1
- package/dist/plugins/api-key/client.d.mts +103 -0
- package/dist/plugins/api-key/client.mjs +4 -1
- package/dist/plugins/api-key/client.mjs.map +1 -1
- package/dist/plugins/api-key/error-codes.d.mts +106 -0
- package/dist/plugins/api-key/error-codes.mjs +34 -0
- package/dist/plugins/api-key/error-codes.mjs.map +1 -0
- package/dist/plugins/api-key/index.d.mts +181 -112
- package/dist/plugins/api-key/index.mjs +7 -34
- package/dist/plugins/api-key/index.mjs.map +1 -1
- package/dist/plugins/api-key/rate-limit.mjs +3 -2
- package/dist/plugins/api-key/rate-limit.mjs.map +1 -1
- package/dist/plugins/api-key/routes/create-api-key.mjs +19 -17
- package/dist/plugins/api-key/routes/create-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/delete-api-key.mjs +7 -5
- package/dist/plugins/api-key/routes/delete-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/get-api-key.mjs +5 -3
- package/dist/plugins/api-key/routes/get-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/update-api-key.mjs +18 -16
- package/dist/plugins/api-key/routes/update-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/verify-api-key.mjs +16 -35
- package/dist/plugins/api-key/routes/verify-api-key.mjs.map +1 -1
- package/dist/plugins/bearer/index.d.mts +3 -3
- package/dist/plugins/captcha/index.d.mts +2 -2
- package/dist/plugins/captcha/index.mjs +3 -3
- package/dist/plugins/captcha/index.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/captchafox.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/captchafox.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/h-captcha.mjs.map +1 -1
- package/dist/plugins/custom-session/index.d.mts +5 -5
- package/dist/plugins/device-authorization/index.d.mts +54 -18
- package/dist/plugins/device-authorization/routes.mjs +18 -18
- package/dist/plugins/device-authorization/routes.mjs.map +1 -1
- package/dist/plugins/email-otp/client.d.mts +15 -0
- package/dist/plugins/email-otp/client.mjs +4 -1
- package/dist/plugins/email-otp/client.mjs.map +1 -1
- package/dist/plugins/email-otp/error-codes.d.mts +18 -0
- package/dist/plugins/email-otp/error-codes.mjs +12 -0
- package/dist/plugins/email-otp/error-codes.mjs.map +1 -0
- package/dist/plugins/email-otp/index.d.mts +64 -55
- package/dist/plugins/email-otp/index.mjs +4 -3
- package/dist/plugins/email-otp/index.mjs.map +1 -1
- package/dist/plugins/email-otp/routes.mjs +30 -35
- package/dist/plugins/email-otp/routes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/client.d.mts +27 -0
- package/dist/plugins/generic-oauth/client.mjs +4 -1
- package/dist/plugins/generic-oauth/client.mjs.map +1 -1
- package/dist/plugins/generic-oauth/error-codes.d.mts +30 -0
- package/dist/plugins/generic-oauth/index.d.mts +55 -37
- package/dist/plugins/generic-oauth/index.mjs +4 -4
- package/dist/plugins/generic-oauth/index.mjs.map +1 -1
- package/dist/plugins/generic-oauth/routes.mjs +11 -12
- package/dist/plugins/generic-oauth/routes.mjs.map +1 -1
- package/dist/plugins/haveibeenpwned/index.d.mts +7 -4
- package/dist/plugins/haveibeenpwned/index.mjs +5 -4
- package/dist/plugins/haveibeenpwned/index.mjs.map +1 -1
- package/dist/plugins/index.d.mts +4 -2
- package/dist/plugins/index.mjs +6 -4
- package/dist/plugins/jwt/index.d.mts +9 -9
- package/dist/plugins/jwt/index.mjs +2 -2
- package/dist/plugins/jwt/index.mjs.map +1 -1
- 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/client.d.mts +10 -14
- package/dist/plugins/multi-session/client.mjs +5 -2
- package/dist/plugins/multi-session/client.mjs.map +1 -1
- package/dist/plugins/multi-session/error-codes.d.mts +10 -0
- package/dist/plugins/multi-session/error-codes.mjs +8 -0
- package/dist/plugins/multi-session/error-codes.mjs.map +1 -0
- package/dist/plugins/multi-session/index.d.mts +18 -14
- package/dist/plugins/multi-session/index.mjs +6 -7
- package/dist/plugins/multi-session/index.mjs.map +1 -1
- 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/error.mjs +1 -1
- package/dist/plugins/oidc-provider/error.mjs.map +1 -1
- package/dist/plugins/oidc-provider/index.d.mts +15 -15
- package/dist/plugins/one-tap/client.d.mts +2 -2
- 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 +229 -2
- package/dist/plugins/organization/client.mjs +3 -1
- package/dist/plugins/organization/client.mjs.map +1 -1
- package/dist/plugins/organization/error-codes.d.mts +224 -56
- package/dist/plugins/organization/organization.d.mts +7 -7
- package/dist/plugins/organization/organization.mjs +4 -4
- package/dist/plugins/organization/organization.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +22 -22
- package/dist/plugins/organization/routes/crud-access-control.mjs +40 -39
- package/dist/plugins/organization/routes/crud-access-control.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-invites.d.mts +58 -58
- package/dist/plugins/organization/routes/crud-invites.mjs +42 -40
- 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-members.mjs +41 -54
- package/dist/plugins/organization/routes/crud-members.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-org.d.mts +51 -51
- package/dist/plugins/organization/routes/crud-org.mjs +28 -25
- package/dist/plugins/organization/routes/crud-org.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-team.d.mts +77 -77
- package/dist/plugins/organization/routes/crud-team.mjs +41 -47
- package/dist/plugins/organization/routes/crud-team.mjs.map +1 -1
- package/dist/plugins/phone-number/client.d.mts +51 -0
- package/dist/plugins/phone-number/client.mjs +4 -1
- package/dist/plugins/phone-number/client.mjs.map +1 -1
- package/dist/plugins/phone-number/error-codes.d.mts +54 -0
- package/dist/plugins/phone-number/index.d.mts +81 -45
- package/dist/plugins/phone-number/index.mjs +2 -2
- package/dist/plugins/phone-number/index.mjs.map +1 -1
- package/dist/plugins/phone-number/routes.mjs +27 -28
- package/dist/plugins/phone-number/routes.mjs.map +1 -1
- package/dist/plugins/siwe/index.d.mts +3 -3
- package/dist/plugins/siwe/index.mjs +7 -6
- package/dist/plugins/siwe/index.mjs.map +1 -1
- package/dist/plugins/two-factor/backup-codes/index.mjs +7 -7
- package/dist/plugins/two-factor/backup-codes/index.mjs.map +1 -1
- package/dist/plugins/two-factor/client.d.mts +39 -0
- package/dist/plugins/two-factor/client.mjs +4 -1
- package/dist/plugins/two-factor/client.mjs.map +1 -1
- package/dist/plugins/two-factor/error-code.d.mts +36 -9
- package/dist/plugins/two-factor/index.d.mts +54 -27
- package/dist/plugins/two-factor/index.mjs +4 -5
- package/dist/plugins/two-factor/index.mjs.map +1 -1
- package/dist/plugins/two-factor/otp/index.mjs +8 -6
- package/dist/plugins/two-factor/otp/index.mjs.map +1 -1
- package/dist/plugins/two-factor/totp/index.mjs +16 -8
- package/dist/plugins/two-factor/totp/index.mjs.map +1 -1
- package/dist/plugins/two-factor/verify-two-factor.mjs +9 -6
- package/dist/plugins/two-factor/verify-two-factor.mjs.map +1 -1
- package/dist/plugins/username/client.d.mts +35 -0
- package/dist/plugins/username/client.mjs +4 -1
- package/dist/plugins/username/client.mjs.map +1 -1
- package/dist/plugins/username/error-codes.d.mts +32 -8
- package/dist/plugins/username/index.d.mts +41 -17
- package/dist/plugins/username/index.mjs +21 -31
- package/dist/plugins/username/index.mjs.map +1 -1
- package/dist/plugins/username/schema.d.mts +3 -3
- package/dist/test-utils/test-instance.d.mts +1349 -1198
- package/dist/utils/is-api-error.d.mts +7 -0
- package/dist/utils/is-api-error.mjs +11 -0
- package/dist/utils/is-api-error.mjs.map +1 -0
- package/dist/utils/password.mjs +3 -3
- package/dist/utils/password.mjs.map +1 -1
- package/dist/utils/plugin-helper.mjs +2 -2
- package/dist/utils/plugin-helper.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-account.mjs","names":["e: any"],"sources":["../../src/oauth2/link-account.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { isDevelopment, logger } from \"@better-auth/core/env\";\nimport { APIError, createEmailVerificationToken } from \"../api\";\nimport { setAccountCookie } from \"../cookies/session-store\";\nimport type { Account, User } from \"../types\";\nimport { setTokenUtil } from \"./utils\";\n\nexport async function handleOAuthUserInfo(\n\tc: GenericEndpointContext,\n\topts: {\n\t\tuserInfo: Omit<User, \"createdAt\" | \"updatedAt\">;\n\t\taccount: Omit<Account, \"id\" | \"userId\" | \"createdAt\" | \"updatedAt\">;\n\t\tcallbackURL?: string | undefined;\n\t\tdisableSignUp?: boolean | undefined;\n\t\toverrideUserInfo?: boolean | undefined;\n\t\tisTrustedProvider?: boolean | undefined;\n\t},\n) {\n\tconst { userInfo, account, callbackURL, disableSignUp, overrideUserInfo } =\n\t\topts;\n\tconst dbUser = await c.context.internalAdapter\n\t\t.findOAuthUser(\n\t\t\tuserInfo.email.toLowerCase(),\n\t\t\taccount.accountId,\n\t\t\taccount.providerId,\n\t\t)\n\t\t.catch((e) => {\n\t\t\tlogger.error(\n\t\t\t\t\"Better auth was unable to query your database.\\nError: \",\n\t\t\t\te,\n\t\t\t);\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=internal_server_error`);\n\t\t});\n\tlet user = dbUser?.user;\n\tlet isRegister = !user;\n\n\tif (dbUser) {\n\t\tconst hasBeenLinked = dbUser.accounts.find(\n\t\t\t(a) =>\n\t\t\t\ta.providerId === account.providerId &&\n\t\t\t\ta.accountId === account.accountId,\n\t\t);\n\t\tif (!hasBeenLinked) {\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\tconst isTrustedProvider =\n\t\t\t\topts.isTrustedProvider ||\n\t\t\t\ttrustedProviders?.includes(account.providerId as \"apple\");\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !userInfo.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tif (isDevelopment()) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`User already exist but account isn't linked to ${account.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\terror: \"account not linked\",\n\t\t\t\t\tdata: null,\n\t\t\t\t};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait c.context.internalAdapter.linkAccount({\n\t\t\t\t\tproviderId: account.providerId,\n\t\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t\t\tuserId: dbUser.user.id,\n\t\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\t\tidToken: account.idToken,\n\t\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\t\tscope: account.scope,\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Unable to link account\", e);\n\t\t\t\treturn {\n\t\t\t\t\terror: \"unable to link account\",\n\t\t\t\t\tdata: null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.emailVerified &&\n\t\t\t\t!dbUser.user.emailVerified &&\n\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t) {\n\t\t\t\tawait c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tif (c.context.options.account?.updateAccountOnSignIn !== false) {\n\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\tObject.entries({\n\t\t\t\t\t\tidToken: account.idToken,\n\t\t\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\t\t\tscope: account.scope,\n\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t);\n\t\t\t\tif (c.context.options.account?.storeAccountCookie) {\n\t\t\t\t\tawait setAccountCookie(c, {\n\t\t\t\t\t\t...account,\n\t\t\t\t\t\t...updateData,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(updateData).length > 0) {\n\t\t\t\t\tawait c.context.internalAdapter.updateAccount(\n\t\t\t\t\t\thasBeenLinked.id,\n\t\t\t\t\t\tupdateData,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.emailVerified &&\n\t\t\t\t!dbUser.user.emailVerified &&\n\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t) {\n\t\t\t\tawait c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (overrideUserInfo) {\n\t\t\tconst { id: _, ...restUserInfo } = userInfo;\n\t\t\t// update user info from the provider if overrideUserInfo is true\n\t\t\tuser = await c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t...restUserInfo,\n\t\t\t\temail: userInfo.email.toLowerCase(),\n\t\t\t\temailVerified:\n\t\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t\t\t\t? dbUser.user.emailVerified || userInfo.emailVerified\n\t\t\t\t\t\t: userInfo.emailVerified,\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif (disableSignUp) {\n\t\t\treturn {\n\t\t\t\terror: \"signup disabled\",\n\t\t\t\tdata: null,\n\t\t\t\tisRegister: false,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst { id: _, ...restUserInfo } = userInfo;\n\t\t\tconst accountData = {\n\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\tidToken: account.idToken,\n\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\tscope: account.scope,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t};\n\t\t\tconst { user: createdUser, account: createdAccount } =\n\t\t\t\tawait c.context.internalAdapter.createOAuthUser(\n\t\t\t\t\t{\n\t\t\t\t\t\t...restUserInfo,\n\t\t\t\t\t\temail: userInfo.email.toLowerCase(),\n\t\t\t\t\t},\n\t\t\t\t\taccountData,\n\t\t\t\t);\n\t\t\tuser = createdUser;\n\t\t\tif (c.context.options.account?.storeAccountCookie) {\n\t\t\t\tawait setAccountCookie(c, createdAccount);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!userInfo.emailVerified &&\n\t\t\t\tuser &&\n\t\t\t\tc.context.options.emailVerification?.sendOnSignUp &&\n\t\t\t\tc.context.options.emailVerification?.sendVerificationEmail\n\t\t\t) {\n\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\tc.context.secret,\n\t\t\t\t\tuser.email,\n\t\t\t\t\tundefined,\n\t\t\t\t\tc.context.options.emailVerification?.expiresIn,\n\t\t\t\t);\n\t\t\t\tconst url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\tawait c.context.runInBackgroundOrAwait(\n\t\t\t\t\tc.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuser,\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tc.request,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (e: any) {\n\t\t\tlogger.error(e);\n\t\t\tif (e instanceof APIError) {\n\t\t\t\treturn {\n\t\t\t\t\terror: e.message,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisRegister: false,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\terror: \"unable to create user\",\n\t\t\t\tdata: null,\n\t\t\t\tisRegister: false,\n\t\t\t};\n\t\t}\n\t}\n\tif (!user) {\n\t\treturn {\n\t\t\terror: \"unable to create user\",\n\t\t\tdata: null,\n\t\t\tisRegister: false,\n\t\t};\n\t}\n\n\tconst session = await c.context.internalAdapter.createSession(user.id);\n\tif (!session) {\n\t\treturn {\n\t\t\terror: \"unable to create session\",\n\t\t\tdata: null,\n\t\t\tisRegister: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tsession,\n\t\t\tuser,\n\t\t},\n\t\terror: null,\n\t\tisRegister,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"link-account.mjs","names":["e: any"],"sources":["../../src/oauth2/link-account.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { isDevelopment, logger } from \"@better-auth/core/env\";\nimport { createEmailVerificationToken } from \"../api\";\nimport { setAccountCookie } from \"../cookies/session-store\";\nimport type { Account, User } from \"../types\";\nimport { isAPIError } from \"../utils/is-api-error\";\nimport { setTokenUtil } from \"./utils\";\n\nexport async function handleOAuthUserInfo(\n\tc: GenericEndpointContext,\n\topts: {\n\t\tuserInfo: Omit<User, \"createdAt\" | \"updatedAt\">;\n\t\taccount: Omit<Account, \"id\" | \"userId\" | \"createdAt\" | \"updatedAt\">;\n\t\tcallbackURL?: string | undefined;\n\t\tdisableSignUp?: boolean | undefined;\n\t\toverrideUserInfo?: boolean | undefined;\n\t\tisTrustedProvider?: boolean | undefined;\n\t},\n) {\n\tconst { userInfo, account, callbackURL, disableSignUp, overrideUserInfo } =\n\t\topts;\n\tconst dbUser = await c.context.internalAdapter\n\t\t.findOAuthUser(\n\t\t\tuserInfo.email.toLowerCase(),\n\t\t\taccount.accountId,\n\t\t\taccount.providerId,\n\t\t)\n\t\t.catch((e) => {\n\t\t\tlogger.error(\n\t\t\t\t\"Better auth was unable to query your database.\\nError: \",\n\t\t\t\te,\n\t\t\t);\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=internal_server_error`);\n\t\t});\n\tlet user = dbUser?.user;\n\tlet isRegister = !user;\n\n\tif (dbUser) {\n\t\tconst hasBeenLinked = dbUser.accounts.find(\n\t\t\t(a) =>\n\t\t\t\ta.providerId === account.providerId &&\n\t\t\t\ta.accountId === account.accountId,\n\t\t);\n\t\tif (!hasBeenLinked) {\n\t\t\tconst trustedProviders =\n\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\tconst isTrustedProvider =\n\t\t\t\topts.isTrustedProvider ||\n\t\t\t\ttrustedProviders?.includes(account.providerId as \"apple\");\n\t\t\tif (\n\t\t\t\t(!isTrustedProvider && !userInfo.emailVerified) ||\n\t\t\t\tc.context.options.account?.accountLinking?.enabled === false\n\t\t\t) {\n\t\t\t\tif (isDevelopment()) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`User already exist but account isn't linked to ${account.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\terror: \"account not linked\",\n\t\t\t\t\tdata: null,\n\t\t\t\t};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait c.context.internalAdapter.linkAccount({\n\t\t\t\t\tproviderId: account.providerId,\n\t\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t\t\tuserId: dbUser.user.id,\n\t\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\t\tidToken: account.idToken,\n\t\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\t\tscope: account.scope,\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Unable to link account\", e);\n\t\t\t\treturn {\n\t\t\t\t\terror: \"unable to link account\",\n\t\t\t\t\tdata: null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.emailVerified &&\n\t\t\t\t!dbUser.user.emailVerified &&\n\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t) {\n\t\t\t\tawait c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tif (c.context.options.account?.updateAccountOnSignIn !== false) {\n\t\t\t\tconst updateData = Object.fromEntries(\n\t\t\t\t\tObject.entries({\n\t\t\t\t\t\tidToken: account.idToken,\n\t\t\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\t\t\tscope: account.scope,\n\t\t\t\t\t}).filter(([_, value]) => value !== undefined),\n\t\t\t\t);\n\t\t\t\tif (c.context.options.account?.storeAccountCookie) {\n\t\t\t\t\tawait setAccountCookie(c, {\n\t\t\t\t\t\t...account,\n\t\t\t\t\t\t...updateData,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(updateData).length > 0) {\n\t\t\t\t\tawait c.context.internalAdapter.updateAccount(\n\t\t\t\t\t\thasBeenLinked.id,\n\t\t\t\t\t\tupdateData,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tuserInfo.emailVerified &&\n\t\t\t\t!dbUser.user.emailVerified &&\n\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t) {\n\t\t\t\tawait c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t\temailVerified: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (overrideUserInfo) {\n\t\t\tconst { id: _, ...restUserInfo } = userInfo;\n\t\t\t// update user info from the provider if overrideUserInfo is true\n\t\t\tuser = await c.context.internalAdapter.updateUser(dbUser.user.id, {\n\t\t\t\t...restUserInfo,\n\t\t\t\temail: userInfo.email.toLowerCase(),\n\t\t\t\temailVerified:\n\t\t\t\t\tuserInfo.email.toLowerCase() === dbUser.user.email\n\t\t\t\t\t\t? dbUser.user.emailVerified || userInfo.emailVerified\n\t\t\t\t\t\t: userInfo.emailVerified,\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif (disableSignUp) {\n\t\t\treturn {\n\t\t\t\terror: \"signup disabled\",\n\t\t\t\tdata: null,\n\t\t\t\tisRegister: false,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst { id: _, ...restUserInfo } = userInfo;\n\t\t\tconst accountData = {\n\t\t\t\taccessToken: await setTokenUtil(account.accessToken, c.context),\n\t\t\t\trefreshToken: await setTokenUtil(account.refreshToken, c.context),\n\t\t\t\tidToken: account.idToken,\n\t\t\t\taccessTokenExpiresAt: account.accessTokenExpiresAt,\n\t\t\t\trefreshTokenExpiresAt: account.refreshTokenExpiresAt,\n\t\t\t\tscope: account.scope,\n\t\t\t\tproviderId: account.providerId,\n\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t};\n\t\t\tconst { user: createdUser, account: createdAccount } =\n\t\t\t\tawait c.context.internalAdapter.createOAuthUser(\n\t\t\t\t\t{\n\t\t\t\t\t\t...restUserInfo,\n\t\t\t\t\t\temail: userInfo.email.toLowerCase(),\n\t\t\t\t\t},\n\t\t\t\t\taccountData,\n\t\t\t\t);\n\t\t\tuser = createdUser;\n\t\t\tif (c.context.options.account?.storeAccountCookie) {\n\t\t\t\tawait setAccountCookie(c, createdAccount);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!userInfo.emailVerified &&\n\t\t\t\tuser &&\n\t\t\t\tc.context.options.emailVerification?.sendOnSignUp &&\n\t\t\t\tc.context.options.emailVerification?.sendVerificationEmail\n\t\t\t) {\n\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\tc.context.secret,\n\t\t\t\t\tuser.email,\n\t\t\t\t\tundefined,\n\t\t\t\t\tc.context.options.emailVerification?.expiresIn,\n\t\t\t\t);\n\t\t\t\tconst url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\tawait c.context.runInBackgroundOrAwait(\n\t\t\t\t\tc.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuser,\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tc.request,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (e: any) {\n\t\t\tlogger.error(e);\n\t\t\tif (isAPIError(e)) {\n\t\t\t\treturn {\n\t\t\t\t\terror: e.message,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisRegister: false,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\terror: \"unable to create user\",\n\t\t\t\tdata: null,\n\t\t\t\tisRegister: false,\n\t\t\t};\n\t\t}\n\t}\n\tif (!user) {\n\t\treturn {\n\t\t\terror: \"unable to create user\",\n\t\t\tdata: null,\n\t\t\tisRegister: false,\n\t\t};\n\t}\n\n\tconst session = await c.context.internalAdapter.createSession(user.id);\n\tif (!session) {\n\t\treturn {\n\t\t\terror: \"unable to create session\",\n\t\t\tdata: null,\n\t\t\tisRegister: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tsession,\n\t\t\tuser,\n\t\t},\n\t\terror: null,\n\t\tisRegister,\n\t};\n}\n"],"mappings":"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"}
|
package/dist/oauth2/state.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { setOAuthState } from "../api/middlewares/oauth.mjs";
|
|
2
2
|
import { generateRandomString } from "../crypto/random.mjs";
|
|
3
3
|
import { symmetricDecrypt, symmetricEncrypt } from "../crypto/index.mjs";
|
|
4
|
+
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
4
5
|
import * as z from "zod";
|
|
5
|
-
import { APIError } from "better-call";
|
|
6
6
|
|
|
7
7
|
//#region src/oauth2/state.ts
|
|
8
8
|
async function generateState(c, link, additionalData) {
|
|
9
9
|
const callbackURL = c.body?.callbackURL || c.context.options.baseURL;
|
|
10
|
-
if (!callbackURL) throw
|
|
10
|
+
if (!callbackURL) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CALLBACK_URL_REQUIRED);
|
|
11
11
|
const codeVerifier = generateRandomString(128);
|
|
12
12
|
const state = generateRandomString(32);
|
|
13
13
|
const storeStateStrategy = c.context.oauthConfig.storeStateStrategy;
|
|
@@ -46,7 +46,7 @@ async function generateState(c, link, additionalData) {
|
|
|
46
46
|
});
|
|
47
47
|
if (!verification) {
|
|
48
48
|
c.context.logger.error("Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database");
|
|
49
|
-
throw
|
|
49
|
+
throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_CREATE_VERIFICATION);
|
|
50
50
|
}
|
|
51
51
|
return {
|
|
52
52
|
state: verification.identifier,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.mjs","names":["stateCookie","parsedData: z.infer<typeof stateDataSchema>"],"sources":["../../src/oauth2/state.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport { setOAuthState } from \"../api/middlewares/oauth\";\nimport {\n\tgenerateRandomString,\n\tsymmetricDecrypt,\n\tsymmetricEncrypt,\n} from \"../crypto\";\n\nexport async function generateState(\n\tc: GenericEndpointContext,\n\tlink:\n\t\t| {\n\t\t\t\temail: string;\n\t\t\t\tuserId: string;\n\t\t }\n\t\t| undefined,\n\tadditionalData: Record<string, any> | false | undefined,\n) {\n\tconst callbackURL = c.body?.callbackURL || c.context.options.baseURL;\n\tif (!callbackURL) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"callbackURL is required\",\n\t\t});\n\t}\n\n\tconst codeVerifier = generateRandomString(128);\n\tconst state = generateRandomString(32);\n\tconst storeStateStrategy = c.context.oauthConfig.storeStateStrategy;\n\n\tconst stateData = {\n\t\t...(additionalData ? additionalData : {}),\n\t\tcallbackURL,\n\t\tcodeVerifier,\n\t\terrorURL: c.body?.errorCallbackURL,\n\t\tnewUserURL: c.body?.newUserCallbackURL,\n\t\tlink,\n\t\t/**\n\t\t * This is the actual expiry time of the state\n\t\t */\n\t\texpiresAt: Date.now() + 10 * 60 * 1000,\n\t\trequestSignUp: c.body?.requestSignUp,\n\t\tstate,\n\t};\n\n\tawait setOAuthState(stateData);\n\n\tif (storeStateStrategy === \"cookie\") {\n\t\t// Store state data in an encrypted cookie\n\t\tconst encryptedData = await symmetricEncrypt({\n\t\t\tkey: c.context.secret,\n\t\t\tdata: JSON.stringify(stateData),\n\t\t});\n\n\t\tconst stateCookie = c.context.createAuthCookie(\"oauth_state\", {\n\t\t\tmaxAge: 10 * 60 * 1000, // 10 minutes\n\t\t});\n\n\t\tc.setCookie(stateCookie.name, encryptedData, stateCookie.attributes);\n\n\t\treturn {\n\t\t\tstate,\n\t\t\tcodeVerifier,\n\t\t};\n\t}\n\n\t// Default: database strategy\n\tconst stateCookie = c.context.createAuthCookie(\"state\", {\n\t\tmaxAge: 5 * 60 * 1000, // 5 minutes\n\t});\n\tawait c.setSignedCookie(\n\t\tstateCookie.name,\n\t\tstate,\n\t\tc.context.secret,\n\t\tstateCookie.attributes,\n\t);\n\n\tconst expiresAt = new Date();\n\texpiresAt.setMinutes(expiresAt.getMinutes() + 10);\n\tconst verification = await c.context.internalAdapter.createVerificationValue({\n\t\tvalue: JSON.stringify(stateData),\n\t\tidentifier: state,\n\t\texpiresAt,\n\t});\n\tif (!verification) {\n\t\tc.context.logger.error(\n\t\t\t\"Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database\",\n\t\t);\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\tmessage: \"Unable to create verification\",\n\t\t});\n\t}\n\treturn {\n\t\tstate: verification.identifier,\n\t\tcodeVerifier,\n\t};\n}\n\nexport async function parseState(c: GenericEndpointContext) {\n\tconst state = c.query.state || c.body.state;\n\tconst storeStateStrategy = c.context.oauthConfig.storeStateStrategy;\n\n\tconst stateDataSchema = z.looseObject({\n\t\tcallbackURL: z.string(),\n\t\tcodeVerifier: z.string(),\n\t\terrorURL: z.string().optional(),\n\t\tnewUserURL: z.string().optional(),\n\t\texpiresAt: z.number(),\n\t\tlink: z\n\t\t\t.object({\n\t\t\t\temail: z.string(),\n\t\t\t\tuserId: z.coerce.string(),\n\t\t\t})\n\t\t\t.optional(),\n\t\trequestSignUp: z.boolean().optional(),\n\t\tstate: z.string().optional(),\n\t});\n\n\tlet parsedData: z.infer<typeof stateDataSchema>;\n\t/**\n\t * This is generally cause security issue and should only be used in\n\t * dev or staging environments. It's currently used by the oauth-proxy\n\t * plugin\n\t */\n\tconst skipStateCookieCheck = c.context.oauthConfig?.skipStateCookieCheck;\n\tif (storeStateStrategy === \"cookie\") {\n\t\t// Retrieve state data from encrypted cookie\n\t\tconst stateCookie = c.context.createAuthCookie(\"oauth_state\");\n\t\tconst encryptedData = c.getCookie(stateCookie.name);\n\n\t\tif (!encryptedData) {\n\t\t\tc.context.logger.error(\"State Mismatch. OAuth state cookie not found\", {\n\t\t\t\tstate,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\ttry {\n\t\t\tconst decryptedData = await symmetricDecrypt({\n\t\t\t\tkey: c.context.secret,\n\t\t\t\tdata: encryptedData,\n\t\t\t});\n\n\t\t\tparsedData = stateDataSchema.parse(JSON.parse(decryptedData));\n\t\t} catch (error) {\n\t\t\tc.context.logger.error(\"Failed to decrypt or parse OAuth state cookie\", {\n\t\t\t\terror,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\tconst skipStateCookieCheck = c.context.oauthConfig?.skipStateCookieCheck;\n\t\tif (\n\t\t\t!skipStateCookieCheck &&\n\t\t\tparsedData.state &&\n\t\t\tparsedData.state !== state\n\t\t) {\n\t\t\tc.context.logger.error(\"State Mismatch. State parameter does not match\", {\n\t\t\t\texpected: parsedData.state,\n\t\t\t\treceived: state,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=state_mismatch`);\n\t\t}\n\n\t\t// Clear the cookie after successful parsing\n\t\tc.setCookie(stateCookie.name, \"\", {\n\t\t\tmaxAge: 0,\n\t\t});\n\t} else {\n\t\t// Default: database strategy\n\t\tconst data = await c.context.internalAdapter.findVerificationValue(state);\n\t\tif (!data) {\n\t\t\tc.context.logger.error(\"State Mismatch. Verification not found\", {\n\t\t\t\tstate,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\tparsedData = stateDataSchema.parse(JSON.parse(data.value));\n\n\t\tconst stateCookie = c.context.createAuthCookie(\"state\");\n\t\tconst stateCookieValue = await c.getSignedCookie(\n\t\t\tstateCookie.name,\n\t\t\tc.context.secret,\n\t\t);\n\n\t\tif (\n\t\t\t!skipStateCookieCheck &&\n\t\t\t(!stateCookieValue || stateCookieValue !== state)\n\t\t) {\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=state_mismatch`);\n\t\t}\n\t\tc.setCookie(stateCookie.name, \"\", {\n\t\t\tmaxAge: 0,\n\t\t});\n\n\t\t// Delete verification value after retrieval\n\t\tawait c.context.internalAdapter.deleteVerificationValue(data.id);\n\t}\n\n\tif (!parsedData.errorURL) {\n\t\tparsedData.errorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t}\n\n\t// Check expiration\n\tif (parsedData.expiresAt < Date.now()) {\n\t\tconst errorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t}\n\n\tif (parsedData) {\n\t\tawait setOAuthState(parsedData);\n\t}\n\n\treturn parsedData;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"state.mjs","names":["stateCookie","parsedData: z.infer<typeof stateDataSchema>"],"sources":["../../src/oauth2/state.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError, BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport * as z from \"zod\";\nimport { setOAuthState } from \"../api/middlewares/oauth\";\nimport {\n\tgenerateRandomString,\n\tsymmetricDecrypt,\n\tsymmetricEncrypt,\n} from \"../crypto\";\n\nexport async function generateState(\n\tc: GenericEndpointContext,\n\tlink:\n\t\t| {\n\t\t\t\temail: string;\n\t\t\t\tuserId: string;\n\t\t }\n\t\t| undefined,\n\tadditionalData: Record<string, any> | false | undefined,\n) {\n\tconst callbackURL = c.body?.callbackURL || c.context.options.baseURL;\n\tif (!callbackURL) {\n\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.CALLBACK_URL_REQUIRED);\n\t}\n\n\tconst codeVerifier = generateRandomString(128);\n\tconst state = generateRandomString(32);\n\tconst storeStateStrategy = c.context.oauthConfig.storeStateStrategy;\n\n\tconst stateData = {\n\t\t...(additionalData ? additionalData : {}),\n\t\tcallbackURL,\n\t\tcodeVerifier,\n\t\terrorURL: c.body?.errorCallbackURL,\n\t\tnewUserURL: c.body?.newUserCallbackURL,\n\t\tlink,\n\t\t/**\n\t\t * This is the actual expiry time of the state\n\t\t */\n\t\texpiresAt: Date.now() + 10 * 60 * 1000,\n\t\trequestSignUp: c.body?.requestSignUp,\n\t\tstate,\n\t};\n\n\tawait setOAuthState(stateData);\n\n\tif (storeStateStrategy === \"cookie\") {\n\t\t// Store state data in an encrypted cookie\n\t\tconst encryptedData = await symmetricEncrypt({\n\t\t\tkey: c.context.secret,\n\t\t\tdata: JSON.stringify(stateData),\n\t\t});\n\n\t\tconst stateCookie = c.context.createAuthCookie(\"oauth_state\", {\n\t\t\tmaxAge: 10 * 60 * 1000, // 10 minutes\n\t\t});\n\n\t\tc.setCookie(stateCookie.name, encryptedData, stateCookie.attributes);\n\n\t\treturn {\n\t\t\tstate,\n\t\t\tcodeVerifier,\n\t\t};\n\t}\n\n\t// Default: database strategy\n\tconst stateCookie = c.context.createAuthCookie(\"state\", {\n\t\tmaxAge: 5 * 60 * 1000, // 5 minutes\n\t});\n\tawait c.setSignedCookie(\n\t\tstateCookie.name,\n\t\tstate,\n\t\tc.context.secret,\n\t\tstateCookie.attributes,\n\t);\n\n\tconst expiresAt = new Date();\n\texpiresAt.setMinutes(expiresAt.getMinutes() + 10);\n\tconst verification = await c.context.internalAdapter.createVerificationValue({\n\t\tvalue: JSON.stringify(stateData),\n\t\tidentifier: state,\n\t\texpiresAt,\n\t});\n\tif (!verification) {\n\t\tc.context.logger.error(\n\t\t\t\"Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database\",\n\t\t);\n\t\tthrow APIError.from(\n\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_VERIFICATION,\n\t\t);\n\t}\n\treturn {\n\t\tstate: verification.identifier,\n\t\tcodeVerifier,\n\t};\n}\n\nexport async function parseState(c: GenericEndpointContext) {\n\tconst state = c.query.state || c.body.state;\n\tconst storeStateStrategy = c.context.oauthConfig.storeStateStrategy;\n\n\tconst stateDataSchema = z.looseObject({\n\t\tcallbackURL: z.string(),\n\t\tcodeVerifier: z.string(),\n\t\terrorURL: z.string().optional(),\n\t\tnewUserURL: z.string().optional(),\n\t\texpiresAt: z.number(),\n\t\tlink: z\n\t\t\t.object({\n\t\t\t\temail: z.string(),\n\t\t\t\tuserId: z.coerce.string(),\n\t\t\t})\n\t\t\t.optional(),\n\t\trequestSignUp: z.boolean().optional(),\n\t\tstate: z.string().optional(),\n\t});\n\n\tlet parsedData: z.infer<typeof stateDataSchema>;\n\t/**\n\t * This is generally cause security issue and should only be used in\n\t * dev or staging environments. It's currently used by the oauth-proxy\n\t * plugin\n\t */\n\tconst skipStateCookieCheck = c.context.oauthConfig?.skipStateCookieCheck;\n\tif (storeStateStrategy === \"cookie\") {\n\t\t// Retrieve state data from encrypted cookie\n\t\tconst stateCookie = c.context.createAuthCookie(\"oauth_state\");\n\t\tconst encryptedData = c.getCookie(stateCookie.name);\n\n\t\tif (!encryptedData) {\n\t\t\tc.context.logger.error(\"State Mismatch. OAuth state cookie not found\", {\n\t\t\t\tstate,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\ttry {\n\t\t\tconst decryptedData = await symmetricDecrypt({\n\t\t\t\tkey: c.context.secret,\n\t\t\t\tdata: encryptedData,\n\t\t\t});\n\n\t\t\tparsedData = stateDataSchema.parse(JSON.parse(decryptedData));\n\t\t} catch (error) {\n\t\t\tc.context.logger.error(\"Failed to decrypt or parse OAuth state cookie\", {\n\t\t\t\terror,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\tconst skipStateCookieCheck = c.context.oauthConfig?.skipStateCookieCheck;\n\t\tif (\n\t\t\t!skipStateCookieCheck &&\n\t\t\tparsedData.state &&\n\t\t\tparsedData.state !== state\n\t\t) {\n\t\t\tc.context.logger.error(\"State Mismatch. State parameter does not match\", {\n\t\t\t\texpected: parsedData.state,\n\t\t\t\treceived: state,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=state_mismatch`);\n\t\t}\n\n\t\t// Clear the cookie after successful parsing\n\t\tc.setCookie(stateCookie.name, \"\", {\n\t\t\tmaxAge: 0,\n\t\t});\n\t} else {\n\t\t// Default: database strategy\n\t\tconst data = await c.context.internalAdapter.findVerificationValue(state);\n\t\tif (!data) {\n\t\t\tc.context.logger.error(\"State Mismatch. Verification not found\", {\n\t\t\t\tstate,\n\t\t\t});\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t\t}\n\n\t\tparsedData = stateDataSchema.parse(JSON.parse(data.value));\n\n\t\tconst stateCookie = c.context.createAuthCookie(\"state\");\n\t\tconst stateCookieValue = await c.getSignedCookie(\n\t\t\tstateCookie.name,\n\t\t\tc.context.secret,\n\t\t);\n\n\t\tif (\n\t\t\t!skipStateCookieCheck &&\n\t\t\t(!stateCookieValue || stateCookieValue !== state)\n\t\t) {\n\t\t\tconst errorURL =\n\t\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\t\tthrow c.redirect(`${errorURL}?error=state_mismatch`);\n\t\t}\n\t\tc.setCookie(stateCookie.name, \"\", {\n\t\t\tmaxAge: 0,\n\t\t});\n\n\t\t// Delete verification value after retrieval\n\t\tawait c.context.internalAdapter.deleteVerificationValue(data.id);\n\t}\n\n\tif (!parsedData.errorURL) {\n\t\tparsedData.errorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t}\n\n\t// Check expiration\n\tif (parsedData.expiresAt < Date.now()) {\n\t\tconst errorURL =\n\t\t\tc.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;\n\t\tthrow c.redirect(`${errorURL}?error=please_restart_the_process`);\n\t}\n\n\tif (parsedData) {\n\t\tawait setOAuthState(parsedData);\n\t}\n\n\treturn parsedData;\n}\n"],"mappings":"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"}
|