49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import { randomBytes, scryptSync } from "node:crypto";
|
|
import { db } from "@kk/db";
|
|
import * as schema from "@kk/db/schema/auth";
|
|
import { env } from "@kk/env/server";
|
|
import { betterAuth } from "better-auth";
|
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
import { tanstackStartCookies } from "better-auth/tanstack-start";
|
|
|
|
export const auth = betterAuth({
|
|
database: drizzleAdapter(db, {
|
|
provider: "sqlite",
|
|
|
|
schema: schema,
|
|
}),
|
|
trustedOrigins: [
|
|
env.CORS_ORIGIN,
|
|
"http://localhost:3000",
|
|
"http://localhost:3001",
|
|
],
|
|
emailAndPassword: {
|
|
enabled: true,
|
|
// Use Cloudflare's native scrypt via node:crypto for better performance
|
|
// This avoids CPU time limit errors on Cloudflare Workers
|
|
password: {
|
|
hash: async (password) => {
|
|
const salt = randomBytes(16).toString("hex");
|
|
const hash = scryptSync(password, salt, 64).toString("hex");
|
|
return `${salt}:${hash}`;
|
|
},
|
|
verify: async ({ hash, password }) => {
|
|
const [salt, key] = hash.split(":");
|
|
if (!salt || !key) return false;
|
|
const keyBuffer = Buffer.from(key, "hex");
|
|
const hashBuffer = scryptSync(password, salt, 64);
|
|
return keyBuffer.equals(hashBuffer);
|
|
},
|
|
},
|
|
},
|
|
user: {
|
|
additionalFields: {
|
|
role: {
|
|
type: "string",
|
|
input: false,
|
|
},
|
|
},
|
|
},
|
|
plugins: [tanstackStartCookies()],
|
|
});
|