1. Install
Xác thực user qua better-auth
1. Cài đặt better-auth
pnpm add better-authPackages: +26 ++++++++++++++++++++++++++ Progress: resolved 423, reused 357, downloaded 0, added 26, done
dependencies:
- better-auth 1.3.4
2. Cập nhật file .env
BETTER_AUTH_SECRET=NGxDlgTN1nFWDwqOnrxNn4sGC9angt6uThiết lập base_url:
BETTER_AUTH_URL=http://localhost:3000 #Base URL of your appKhi production thực tế, thay localhost bằng domain
3.Tạo file yêu cầu xác thực
Cần tạo ra file auth.ts để tiến hành xác thực
- Nên để vị trí file:
src/lib/auth.ts - Hoặc vị trí: src/
utils/auth.ts
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...
});4.Cấu hình Database NEON và Prisma
Thêm cấu hình DB vào trong file auth.ts
- Chọn Neon làm nơi lưu trữ thông tin người dùng
- Chọn Prisma làm ORM
4.1 Cấu hình database NEON
- Truy cập neon.tech
- Tạo dự án mới
- Ấn nút connect để lấy connection string
Cập nhật file .env
Thêm dòng sau:
DATABASE_URL="postgresql://neondb_owner:password@ep-late-mode-a1cbri6s-pooler.ap-southeast-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require"4.2 Cài đặt Prisma
Thêm Prisma
- Cài prisma ở chế độ phát triển
pnpm add -D prisma- Thêm mô tả vào package.json
"devDependencies": {
"prisma": "^5.x.x"
}- bổ sung mã nguồn vào node_modules và .pnpm
- Cài client để kết nối với database
pnpm add @prisma/client- Khởi tạo prisma
pnpm dlx prisma initnpx prisma init --db- Kiểm tra, bổ sung Database_url vào .env (nếu có rồi thì thôi)
- Tạo thư mục prisma
- Tạo file
schema.prismacó cấu hình
datasource db {
provider = "postgresql" // hoặc sqlite, mysql, v.v.
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}- thông số
--dbgiúp prisma hỏi tên database và tự cấu hình. Nếu bạn chạy local, không cần dùng prisma cloud thì hãy bỏ qua tham só này
- Kết nối Better Auth với Prisma
Thông qua Adapter
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
// If your Prisma file is located elsewhere, you can change the path
import { PrismaClient } from "@/generated/prisma";
const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "sqlite", // or "mysql", "postgresql", ...etc
}),
});hoặc Drizzle (tham khảo phần Drizzle)
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db"; // your drizzle instance
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg", // or "mysql", "sqlite"
}),
});- Tạo thư viện Prisma Client
pnpm prisma generate- Tạo ra thư viện trong src\generated\prisma
5. Tạo bảng cơ sở dữ liệu
Chuẩn hoá lại bảng dữ liệu trong schema
pnpm dlx @better-auth/cli generate- File prisma.schema sẽ được tạo lại, bạn gõ Y để ghi đè lên
√ The file ./prisma/schema.prisma already exists. Do you want to overwrite the schema to the file? ... yes 2025-08-05T02:37:49.926Z SUCCESS [Better Auth]: 🚀 Schema was overwritten successfully!
Chạy lệnh tạo bảng dữ liệu
pnpm prisma db push- Vào Neon để kiểm tra lại các bảng có tạo ra không
Environment variables loaded from .env Prisma schema loaded from prisma\schema.prisma Datasource "db": PostgreSQL database "neondb", schema "public" at "ep-old-recipe-a1ut1oji-pooler.ap-southeast-1.aws.neon.tech"
Your database is now in sync with your Prisma schema. Done in 2.65s
✔ Generated Prisma Client (v6.13.0) to .\src\generated\prisma in 115ms
6. Lựa chọn phương pháp xác thực
- Cấu hình trong file auth.ts
- Hỗ trợ các loại xác thực email/pass, oauth ..
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...other options
emailAndPassword: {
enabled: true,
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
});6.1 Sử dụng Email (mặc định)
export const auth = betterAuth({
//...other options
emailAndPassword: {
enabled: true,
},
});- Nếu muốn tắt, chuyển true --> false
6.2 Sử dụng Oauth Google
Cập nhật lại file .env
# Oauth Google (hiai)
# Author URI Local = http://localhost:3000
# Redirect URI Local = http://localhost:3000/api/auth/callback/google
GOOGLE_CLIENT_ID="1050187222533-id84j5ifdv9s7crsvvg4mma79it0b3sa.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="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"7. Xử lý xác thực trên Backend
import { auth } from "@/lib/auth"; // path to your auth file
import { toNextJsHandler } from "better-auth/next-js";
export const { POST, GET } = toNextJsHandler(auth);- Endpoit trên BE để xử lý liên quan xác thực.
8. Client để gọi hàm signIn(), signUp(), signOut()
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({
/** The base URL of the server (optional if you're using the same domain) */
baseURL: "http://localhost:3000"
})Thủ thuật tạo một instance Prisma duy nhất
-
Khi phát triển với Next.js, bạn dễ vô tình tạo nhiều Prisma Client instance, đặc biệt do hot-reload.
-
Điều này gây ngốn tài nguyên và lỗi khó lường. https://www.prisma.io/docs/orm/more/help-and-troubleshooting/nextjs-help
⚙️ Nguyên nhân:
-
Next.js trong chế độ dev reload module liên tục.
-
Mỗi lần reload = tạo mới Prisma Client ⇒ nhiều instance cùng tồn tại.
✅ Giải pháp khuyên dùng:
- Chỉ tạo 1 instance duy nhất bằng cách gán vào biến toàn cục (global):
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;Ví dụ: Khi dùng lệnh tạo thư viện pnpm prisma generate
mặc định sẽ tạo src/generated/prisma
Khi đó lệnh import sẽ thành
import { PrismaClient } from "@/generated/prisma";