UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

1 lines • 23.9 kB
{"version":3,"file":"sign-in.mjs","names":[],"sources":["../../../src/api/routes/sign-in.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { SocialProviderListEnum } from \"@better-auth/core/social-providers\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport type { InferUser } from \"../../types\";\nimport { generateState } from \"../../utils\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nconst socialSignInBodySchema = z.object({\n\t/**\n\t * Callback URL to redirect to after the user\n\t * has signed in.\n\t */\n\tcallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to after the user has signed in\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * callback url to redirect if the user is newly registered.\n\t *\n\t * useful if you have different routes for existing users and new users\n\t */\n\tnewUserCallbackURL: z.string().optional(),\n\t/**\n\t * Callback url to redirect to if an error happens\n\t *\n\t * If it's initiated from the client sdk this defaults to\n\t * the current url.\n\t */\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to if an error happens\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * OAuth2 provider to use`\n\t */\n\tprovider: SocialProviderListEnum,\n\t/**\n\t * Disable automatic redirection to the provider\n\t *\n\t * This is useful if you want to handle the redirection\n\t * yourself like in a popup or a different tab.\n\t */\n\tdisableRedirect: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Disable automatic redirection to the provider. Useful for handling the redirection yourself\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * ID token from the provider\n\t *\n\t * This is used to sign in the user\n\t * if the user is already signed in with the\n\t * provider in the frontend.\n\t *\n\t * Only applicable if the provider supports\n\t * it. Currently only `apple` and `google` is\n\t * supported out of the box.\n\t */\n\tidToken: z.optional(\n\t\tz.object({\n\t\t\t/**\n\t\t\t * ID token from the provider\n\t\t\t */\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"ID token from the provider\",\n\t\t\t}),\n\t\t\t/**\n\t\t\t * The nonce used to generate the token\n\t\t\t */\n\t\t\tnonce: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Nonce used to generate the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Access token from the provider\n\t\t\t */\n\t\t\taccessToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Access token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Refresh token from the provider\n\t\t\t */\n\t\t\trefreshToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Refresh token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Expiry date of the token\n\t\t\t */\n\t\t\texpiresAt: z\n\t\t\t\t.number()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Expiry date of the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t),\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Array of scopes to request from the provider. This will override the default scopes passed.\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Explicitly request sign-up\n\t *\n\t * Should be used to allow sign up when\n\t * disableImplicitSignUp for this provider is\n\t * true\n\t */\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\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * The login hint to use for the authorization code request\n\t */\n\tloginHint: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The login hint to use for the authorization code request\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Additional data to be passed through the OAuth flow\n\t */\n\tadditionalData: z.record(z.string(), z.any()).optional().meta({\n\t\tdescription: \"Additional data to be passed through the OAuth flow\",\n\t}),\n});\n\nexport const signInSocial = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/social\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"socialSignIn\",\n\t\t\tbody: socialSignInBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as z.infer<typeof socialSignInBodySchema>,\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken?: string | undefined;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser?: InferUser<O> | undefined;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Sign in with a social provider\",\n\t\t\t\t\toperationId: \"socialSignIn\",\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\"Success - Returns either session details or redirect URL\",\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\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\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\tenum: [false],\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: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tc,\n\t\t): Promise<\n\t\t\t| { redirect: boolean; url: string }\n\t\t\t| { redirect: boolean; token: string; url: undefined; user: InferUser<O> }\n\t\t> => {\n\t\t\tconst provider = c.context.socialProviders.find(\n\t\t\t\t(p) => p.id === c.body.provider,\n\t\t\t);\n\t\t\tif (!provider) {\n\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (c.body.idToken) {\n\t\t\t\tif (!provider.verifyIdToken) {\n\t\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\t\"Provider does not support id token verification\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst { token, nonce } = c.body.idToken;\n\t\t\t\tconst valid = await provider.verifyIdToken(token, nonce);\n\t\t\t\tif (!valid) {\n\t\t\t\t\tc.context.logger.error(\"Invalid id token\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst userInfo = await provider.getUserInfo({\n\t\t\t\t\tidToken: token,\n\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t\t});\n\t\t\t\tif (!userInfo || !userInfo?.user) {\n\t\t\t\t\tc.context.logger.error(\"Failed to get user info\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!userInfo.user.email) {\n\t\t\t\t\tc.context.logger.error(\"User email not found\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst data = await handleOAuthUserInfo(c, {\n\t\t\t\t\tuserInfo: {\n\t\t\t\t\t\t...userInfo.user,\n\t\t\t\t\t\temail: userInfo.user.email,\n\t\t\t\t\t\tid: String(userInfo.user.id),\n\t\t\t\t\t\tname: userInfo.user.name || \"\",\n\t\t\t\t\t\timage: userInfo.user.image,\n\t\t\t\t\t\temailVerified: userInfo.user.emailVerified || false,\n\t\t\t\t\t},\n\t\t\t\t\taccount: {\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: String(userInfo.user.id),\n\t\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\t},\n\t\t\t\t\tcallbackURL: c.body.callbackURL,\n\t\t\t\t\tdisableSignUp:\n\t\t\t\t\t\t(provider.disableImplicitSignUp && !c.body.requestSignUp) ||\n\t\t\t\t\t\tprovider.disableSignUp,\n\t\t\t\t});\n\t\t\t\tif (data.error) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: data.error,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(c, data.data!);\n\t\t\t\treturn c.json({\n\t\t\t\t\tredirect: false,\n\t\t\t\t\ttoken: data.data!.session.token,\n\t\t\t\t\turl: undefined,\n\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\tc.context.options,\n\t\t\t\t\t\tdata.data!.user,\n\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { codeVerifier, state } = await generateState(\n\t\t\t\tc,\n\t\t\t\tundefined,\n\t\t\t\tc.body.additionalData,\n\t\t\t);\n\t\t\tconst url = await provider.createAuthorizationURL({\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t\tscopes: c.body.scopes,\n\t\t\t\tloginHint: c.body.loginHint,\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\turl: url.toString(),\n\t\t\t\tredirect: !c.body.disableRedirect,\n\t\t\t});\n\t\t},\n\t);\n\nexport const signInEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"signInEmail\",\n\t\t\tbody: z.object({\n\t\t\t\t/**\n\t\t\t\t * Email of the user\n\t\t\t\t */\n\t\t\t\temail: z.string().meta({\n\t\t\t\t\tdescription: \"Email of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Password of the user\n\t\t\t\t */\n\t\t\t\tpassword: z.string().meta({\n\t\t\t\t\tdescription: \"Password of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Callback URL to use as a redirect for email\n\t\t\t\t * verification and for possible redirects\n\t\t\t\t */\n\t\t\t\tcallbackURL: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Callback URL to use as a redirect for email verification\",\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t\t/**\n\t\t\t\t * If this is false, the session will not be remembered\n\t\t\t\t * @default true\n\t\t\t\t */\n\t\t\t\trememberMe: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"If this is false, the session will not be remembered. Default is `true`.\",\n\t\t\t\t\t})\n\t\t\t\t\t.default(true)\n\t\t\t\t\t.optional(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tpassword: string;\n\t\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t\t},\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken: string;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser: InferUser<O>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signInEmail\",\n\t\t\t\t\tdescription: \"Sign in with email and password\",\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\"Success - Returns either session details or redirect URL\",\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\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\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\tenum: [false],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Session token\",\n\t\t\t\t\t\t\t\t\t\t\t},\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\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tctx,\n\t\t): Promise<{\n\t\t\tredirect: boolean;\n\t\t\ttoken: string;\n\t\t\turl?: string | undefined;\n\t\t\tuser: InferUser<O>;\n\t\t}> => {\n\t\t\tif (!ctx.context.options?.emailAndPassword?.enabled) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\"Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!\",\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email and password is not enabled\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { email, password } = ctx.body;\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\t// Hash password to prevent timing attacks from revealing valid email addresses\n\t\t\t\t// By hashing passwords for invalid emails, we ensure consistent response times\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"User not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst credentialAccount = user.accounts.find(\n\t\t\t\t(a) => a.providerId === \"credential\",\n\t\t\t);\n\t\t\tif (!credentialAccount) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Credential account not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst currentPassword = credentialAccount?.password;\n\t\t\tif (!currentPassword) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Password not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst validPassword = await ctx.context.password.verify({\n\t\t\t\thash: currentPassword,\n\t\t\t\tpassword,\n\t\t\t});\n\t\t\tif (!validPassword) {\n\t\t\t\tctx.context.logger.error(\"Invalid password\");\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tctx.context.options?.emailAndPassword?.requireEmailVerification &&\n\t\t\t\t!user.user.emailVerified\n\t\t\t) {\n\t\t\t\tif (!ctx.context.options?.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (ctx.context.options?.emailVerification?.sendOnSignIn) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tuser.user.email,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t);\n\t\t\t\t\tconst callbackURL = ctx.body.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.body.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tuser.user.id,\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\n\t\t\tif (!session) {\n\t\t\t\tctx.context.logger.error(\"Failed to create session\");\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait setSessionCookie(\n\t\t\t\tctx,\n\t\t\t\t{\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: user.user,\n\t\t\t\t},\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tredirect: !!ctx.body.callbackURL,\n\t\t\t\ttoken: session.token,\n\t\t\t\turl: ctx.body.callbackURL,\n\t\t\t\tuser: parseUserOutput(ctx.context.options, user.user) as InferUser<O>,\n\t\t\t});\n\t\t},\n\t);\n"],"mappings":"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"}