feat: enable auth openapi and password checks

This commit is contained in:
2026-06-10 02:29:46 -07:00
parent 9e0f751489
commit 987c208f88
4 changed files with 37 additions and 2 deletions

View File

@@ -1,5 +1,8 @@
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import { buildAuthEmail, sendEmail } from "./email";
import { trustedOrigins, type Env } from "./env"; import { trustedOrigins, type Env } from "./env";
import { passwordPolicy } from "./password";
import { createAuthPlugins } from "./plugins";
export function createAuth(env: Env) { export function createAuth(env: Env) {
return betterAuth({ return betterAuth({
@@ -9,6 +12,21 @@ export function createAuth(env: Env) {
trustedOrigins: trustedOrigins(env), trustedOrigins: trustedOrigins(env),
emailAndPassword: { emailAndPassword: {
enabled: true, enabled: true,
...passwordPolicy,
requireEmailVerification: true,
revokeSessionsOnPasswordReset: true,
sendResetPassword: async ({ user, url }) => {
await sendEmail(env, buildAuthEmail({ kind: "reset-password", to: user.email, url }));
},
}, },
emailVerification: {
sendOnSignUp: true,
sendOnSignIn: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, url }) => {
await sendEmail(env, buildAuthEmail({ kind: "verify-email", to: user.email, url }));
},
},
plugins: createAuthPlugins(env),
}); });
} }

4
src/password.ts Normal file
View File

@@ -0,0 +1,4 @@
export const passwordPolicy = {
minPasswordLength: 12,
maxPasswordLength: 128,
};

12
src/plugins.ts Normal file
View File

@@ -0,0 +1,12 @@
import type { BetterAuthPlugin } from "better-auth";
import { haveIBeenPwned, openAPI } from "better-auth/plugins";
import type { Env } from "./env";
export function createAuthPlugins(_env: Env): BetterAuthPlugin[] {
return [
openAPI(),
haveIBeenPwned({
customPasswordCompromisedMessage: "This password has appeared in a data breach.",
}),
];
}

View File

@@ -18,9 +18,10 @@ describe("cfw-auth worker", () => {
expect(response.status).toBe(404); expect(response.status).toBe(404);
}); });
it("routes Better Auth traffic through /api/auth/*", async () => { it("exposes Better Auth OpenAPI reference", async () => {
const response = await worker.fetch(new Request("http://auth.local/api/auth/reference"), env); const response = await worker.fetch(new Request("http://auth.local/api/auth/reference"), env);
expect([200, 404, 500]).toContain(response.status); expect(response.status).toBe(200);
expect(response.headers.get("content-type") ?? "").toContain("text/html");
}); });
it("applies configured CORS origin for auth routes", async () => { it("applies configured CORS origin for auth routes", async () => {