import { passkey } from "@better-auth/passkey"; import type { BetterAuthPlugin } from "better-auth"; import { admin, captcha, emailOTP, genericOAuth, haveIBeenPwned, jwt, lastLoginMethod, multiSession, openAPI, twoFactor, bearer, } from "better-auth/plugins"; import { buildAuthEmail, sendEmail } from "./email"; import { booleanEnv, type Env } from "./env"; import { createGenericOAuthProviders } from "./oauth"; export function createAuthPlugins(env: Env): BetterAuthPlugin[] { const plugins: BetterAuthPlugin[] = [ openAPI(), haveIBeenPwned({ customPasswordCompromisedMessage: "This password has appeared in a data breach.", }), emailOTP({ otpLength: 6, expiresIn: 300, allowedAttempts: 3, storeOTP: "hashed", sendVerificationOnSignUp: true, overrideDefaultEmailVerification: false, sendVerificationOTP: async ({ email, otp }) => { await sendEmail(env, buildAuthEmail({ kind: "email-otp", to: email, otp })); }, }), twoFactor(), multiSession({ maximumSessions: 10 }), lastLoginMethod({ storeInDatabase: true }), admin(), ]; if (env.CAPTCHA_PROVIDER === "cloudflare-turnstile" && env.CAPTCHA_SECRET_KEY) { plugins.push( captcha({ provider: "cloudflare-turnstile", secretKey: env.CAPTCHA_SECRET_KEY, endpoints: ["/sign-up/email", "/sign-in/email", "/forget-password"], }), ); } const genericProviders = createGenericOAuthProviders(env); if (genericProviders.length > 0) { plugins.push(genericOAuth({ config: genericProviders })); } if (env.PASSKEY_RP_ID && env.PASSKEY_RP_NAME && env.PASSKEY_ORIGIN) { plugins.push( passkey({ rpID: env.PASSKEY_RP_ID, rpName: env.PASSKEY_RP_NAME, origin: env.PASSKEY_ORIGIN, }), ); } if (booleanEnv(env.ENABLE_JWT)) { plugins.push(jwt()); } if (booleanEnv(env.ENABLE_BEARER)) { plugins.push(bearer()); } return plugins; }