feat: Integrate bcryptjs for password verification in BetterAuth

- Added bcryptjs as a dependency for handling password verification.
- Updated the defineConfig function to support bcrypt password hashes migrated from Clerk.
- Implemented a new password verification method that checks for bcrypt hashes and falls back to BetterAuth's default verification.
This commit is contained in:
YuTengjing
2025-12-25 19:44:36 +08:00
parent 2e7076a9fd
commit 180ebfdf70
2 changed files with 22 additions and 2 deletions
+2
View File
@@ -234,6 +234,7 @@
"antd": "^6.1.1",
"antd-style": "^3.7.1",
"async-retry": "^1.3.3",
"bcryptjs": "^3.0.3",
"better-auth": "^1.4.7",
"better-auth-harmony": "^1.2.5",
"brotli-wasm": "^3.0.1",
@@ -373,6 +374,7 @@
"@testing-library/react": "^16.3.1",
"@testing-library/user-event": "^14.6.1",
"@types/async-retry": "^1.4.9",
"@types/bcryptjs": "^3.0.0",
"@types/chroma-js": "^3.1.2",
"@types/crypto-js": "^4.2.2",
"@types/debug": "^4.1.12",
+20 -2
View File
@@ -3,11 +3,13 @@ import { expo } from '@better-auth/expo';
import { passkey } from '@better-auth/passkey';
import { createNanoId, idGenerator, serverDB } from '@lobechat/database';
import * as schema from '@lobechat/database/schemas';
import bcrypt from 'bcryptjs';
import { emailHarmony } from 'better-auth-harmony';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { BetterAuthOptions, betterAuth } from 'better-auth/minimal';
import { verifyPassword as defaultVerifyPassword } from 'better-auth/crypto';
import { betterAuth } from 'better-auth/minimal';
import { admin, emailOTP, genericOAuth, magicLink } from 'better-auth/plugins';
import { BetterAuthPlugin } from 'better-auth/types';
import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth/types';
import { authEnv } from '@/envs/auth';
import {
@@ -84,6 +86,22 @@ export function defineConfig(customOptions: CustomBetterAuthOptions) {
minPasswordLength: 8,
requireEmailVerification: authEnv.NEXT_PUBLIC_AUTH_EMAIL_VERIFICATION,
// Compatible with bcrypt password hashes migrated from Clerk; after login, you can re-hash in the backend using BetterAuth's default scrypt.
password: {
// New passwords continue to use BetterAuth's default hash to stay consistent with the official configuration.
async verify({ hash, password }: { hash: string; password: string }): Promise<boolean> {
if (!hash) return false;
// Compatible with bcrypt hashes exported from Clerk (starting with $2a$ or $2b$)
if (hash.startsWith('$2a$') || hash.startsWith('$2b$')) {
return bcrypt.compare(password, hash);
}
// For all other cases, use BetterAuth's default verification
return defaultVerifyPassword({ hash, password });
},
},
sendResetPassword: async ({ user, url }) => {
const template = getResetPasswordEmailTemplate({ url });