之前一直使用NextAuth,不过社区名声一直不好,文档陈旧,逻辑耦合严重,于是乎,大家用脚投票有了新选择BetterAuth:
BetterAuth:
Better Auth 是一个与框架无关的 TypeScript 身份验证和授权框架。它提供了一套全面的开箱即用功能,并包含一个插件生态系统,简化了高级功能的添加。无论您需要双因素身份验证 (2FA)、多租户、多会话支持,还是像单点登录 (SSO) 这样的企业级功能,它都能让您专注于构建应用程序,而无需重复造轮子。
1.安装:
bun add better-auth
2.设置环境变量:
// .env BETTER_AUTH_SECRET=
3.设置基本URL:
这个是给betterAuth用的,服务端都会基于这个host来进行请求
BETTER_AUTH_URL=http://localhost:3000 #Base URL of your app
4.初始化Auth:
// lib/auth.ts import { betterAuth } from 'better-auth' import { drizzleAdapter } from 'better-auth/adapters/drizzle' import { nextCookies } from 'better-auth/next-js' import { db } from '@/lib/db' // your drizzle instance import * as schema from '@/lib/db/schema' // 导入 schema //TEST-5 export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL || 'http://localhost:3000', trustedOrigins: [ 'http://localhost:3000', 'https://localhost:3000', ...(process.env.NODE_ENV === 'production' ? [process.env.BETTER_AUTH_URL || ''] : []), ], advanced: { cookiePrefix: '***',//你的cookie前缀 }, database: drizzleAdapter(db, { provider: 'pg', schema, }), emailAndPassword: { enabled: true, autoSignIn: true, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, plugins: [ nextCookies(), // 确保这是最后一个插件 ], })
5.创建数据库表:
因为现在BetterAuth的业务逻辑确定使用了固定的数据库表,你不可以随便改这几张表,所以让他们保留着就好;
npx @better-auth/cli generate
6.处理路由:
要处理 API 请求,您需要在服务器上设置路由处理程序。
// app/api/ath/[...all]route.ts import { auth } from "@/lib/auth"; // path to your auth file import { toNextJsHandler } from "better-auth/next-js"; export const { POST, GET } = toNextJsHandler(auth);
7.创建客户端实例
建议你也自己封装一个客户端实例,这样不用每个地方都舒适化,写这坨胶水代码
// lib/auth-client.ts import { createAuthClient } from 'better-auth/react' export const authClient = createAuthClient() export const { signIn, signUp, signOut, useSession } = authClient
8.客户端使用:
使用session:
const { data: session } = authClient.useSession()
邮箱登录:
const { data, error } = await authClient.signIn.email({ /** * The user email */ email, /** * The user password */ password, /** * A URL to redirect to after the user verifies their email (optional) */ callbackURL: "/dashboard", /** * remember the user session after the browser is closed. * @default true */ rememberMe: false }, { //callbacks })
谷歌登录:
const signIn = async () => { await authClient.signIn.social({ provider: 'google', }) }
登出:
await authClient.signOut()
9.服务端使用:
// src/api/product/route.ts import { auth } from '@/lib/auth' import { auth } from '@/lib/auth' import { createProject, updateProject } from '@/lib/db/projects' import { NextResponse } from 'next/server' import { headers } from 'next/headers' import { logger } from '@/lib/logger' export async function POST(request: Request) { try { const { projectName } = await request.json() const session = await auth.api.getSession({ headers: await headers(), }) if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const userId = session.user.id const project = await createProject(projectName, userId) return NextResponse.json({ projectId: project.projectId }) } catch (error) { logger.error('Error in product route', { error }) return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ) } }