diff --git a/src/plugins.ts b/src/plugins.ts index a2670eb..b458572 100644 --- a/src/plugins.ts +++ b/src/plugins.ts @@ -1,5 +1,6 @@ import type { BetterAuthPlugin } from "better-auth"; -import { captcha, haveIBeenPwned, openAPI } from "better-auth/plugins"; +import { captcha, emailOTP, haveIBeenPwned, openAPI } from "better-auth/plugins"; +import { buildAuthEmail, sendEmail } from "./email"; import type { Env } from "./env"; export function createAuthPlugins(env: Env): BetterAuthPlugin[] { @@ -8,6 +9,17 @@ export function createAuthPlugins(env: Env): BetterAuthPlugin[] { 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 })); + }, + }), ]; if (env.CAPTCHA_PROVIDER === "cloudflare-turnstile" && env.CAPTCHA_SECRET_KEY) { diff --git a/tests/auth-config.test.ts b/tests/auth-config.test.ts index 212f4cf..8a200d1 100644 --- a/tests/auth-config.test.ts +++ b/tests/auth-config.test.ts @@ -90,4 +90,12 @@ describe("auth plugins", () => { }); expect(plugins.map((plugin) => plugin.id)).toContain("captcha"); }); + + it("enables email otp plugin by default", () => { + const plugins = createAuthPlugins({ + BETTER_AUTH_URL: "http://localhost:8788", + TRUSTED_ORIGINS: "http://localhost:8787", + }); + expect(plugins.map((plugin) => plugin.id)).toContain("email-otp"); + }); });