如何使用 Prisma ORM 搭配 Auth.js 與 Next.js
簡介
Auth.js 是一個靈活的開源驗證函式庫,旨在簡化為您的 Next.js 應用程式新增驗證功能的操作。
在本指南中,您將把 Auth.js 整合到一個全新的 Next.js 應用程式中,並將使用者資料持久化儲存於 Prisma Postgres 資料庫中。您可以在 GitHub 上找到本指南的完整範例。
先決條件
- Node.js 20+
- 需基本熟悉 Next.js App Router 與 Prisma
1. 設定您的專案
建立一個新的 Next.js 應用程式
npx create-next-app@latest authjs-prisma
它會提示您自訂設定。請選擇預設值
- 您想使用 TypeScript 嗎?
Yes - 您想使用 ESLint 嗎?
Yes - 您想使用 Tailwind CSS 嗎?
Yes - 您想將程式碼放在
src/目錄中嗎?No - 您想使用 App Router 嗎? (推薦)
Yes - 您想在
next dev中使用 Turbopack 嗎?Yes - 您想自訂匯入別名 (預設為
@/*) 嗎?No
導覽至專案目錄
cd authjs-prisma
2. 安裝並設定 Prisma
2.1. 安裝依賴項目
要開始使用 Prisma,您需要安裝一些依賴項目
npm install prisma tsx @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg dotenv pg
如果您使用的是不同的資料庫提供者(MySQL、SQL Server、SQLite),請安裝相應的驅動程式適配器套件,而不是 @prisma/adapter-pg。如需更多資訊,請參閱資料庫驅動程式。
安裝完成後,在您的專案中初始化 Prisma
npx prisma init --db --output ../app/generated/prisma
在設定 Prisma Postgres 資料庫時,您需要回答幾個問題。請選擇最接近您所在地區的位置,並為您的資料庫取一個易記的名稱,例如 "My Auth.js Project"
這將建立:
- 一個包含
schema.prisma檔案的prisma目錄。 - 一個用於設定 Prisma 的
prisma.config.ts檔案 - 一個 Prisma Postgres 資料庫。
- 一個在專案根目錄下包含
DATABASE_URL的.env檔案。 - 一個指定 Prisma Client 生成位置的 schema 設定 (
../app/generated/prisma)。
2.2. 定義您的 Prisma Schema
在 prisma/schema.prisma 檔案中,將 provider 更改為 prisma-client,並將 vercel-edge 執行時期新增至 generator
generator client {
provider = "prisma-client"
output = "../app/generated/prisma"
runtime = "vercel-edge"
}
datasource db {
provider = "postgresql"
}
將以下模型新增至 schema.prisma 檔案中,這些模型由 Auth.js 提供
model Account {
id String @id @default(cuid())
userId String @map("user_id")
type String
provider String
providerAccountId String @map("provider_account_id")
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@map("accounts")
}
model Session {
id String @id @default(cuid())
sessionToken String @unique @map("session_token")
userId String @map("user_id")
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime? @map("email_verified")
image String?
accounts Account[]
sessions Session[]
@@map("users")
}
model VerificationToken {
identifier String
token String
expires DateTime
@@unique([identifier, token])
@@map("verification_tokens")
}
這會建立以下模型
-
Account:儲存 OAuth 提供者資訊(存取權杖、更新權杖、提供者帳戶 ID),讓使用者能透過多個提供者登入,同時保持單一使用者紀錄。 -
Session:透過唯一的連線權杖、使用者 ID 與過期時間來追蹤已驗證的使用者連線,以維護跨請求的驗證狀態。 -
User:儲存使用者資訊(姓名、電子郵件、個人頭像)的核心模型。使用者可以擁有多個來自不同提供者的帳戶以及多個有效連線。 -
VerificationToken:為電子郵件驗證、密碼重設及其他安全性操作儲存帶有過期時間的臨時權杖。
2.3 在 prisma.config.ts 加入 dotenv
要存取 .env 檔案中的變數,可以透過執行階段載入,或是使用 dotenv。在 prisma.config.ts 的頂部包含一個 dotenv 的匯入:
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
datasource: {
url: env('DATABASE_URL'),
},
});
2.4. 設定 Prisma Client 生成器
現在,執行以下指令來建立資料庫表格並產生 Prisma Client
npx prisma migrate dev --name init
npx prisma generate
2.5 建立 Prisma Client
在根目錄建立一個名為 lib 的新資料夾,並在其中建立一個名為 prisma.ts 的新檔案。此檔案將包含 Prisma Client
import { PrismaClient } from '../app/generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
})
const globalForPrisma = global as unknown as {
prisma: PrismaClient
}
const prisma = globalForPrisma.prisma || new PrismaClient({
adapter,
})
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
3. 設定 Auth.js 憑證
3.1. 安裝相依套件
安裝 Auth.js 的相依套件
npm install @auth/prisma-adapter next-auth@beta
3.2 憑證 (Credentials)
在本指南中,您將設定 Github 的 OAuth。為此,您需要 3 個環境變數
AUTH_SECRET- 由 Auth.js 提供CLIENT_ID- 由 Github 提供CLIENT_SECRET- 由 Github 提供
要取得 AUTH_SECRET,您可以執行以下指令
npx auth secret --copy
--copy會將金鑰複製到您的剪貼簿。(通常,執行npx auth secret就會將金鑰新增至.env.local檔案。若要保持整潔,您可以使用--copy並將其新增至 Prisma 先前建立的.env檔案中。)
將以下內容新增至 .env 檔案
DATABASE_URL=<YOUR_DATABASE_URL>
AUTH_SECRET=<YOUR_AUTH_SECRET>
要取得 CLIENT_ID 與 CLIENT_SECRET,您可以在 Github 上建立一個新的 OAuth 應用程式。
- 導覽至 Github 開發者設定
- 點擊
New OAuth App - 輸入您的應用程式名稱、首頁 URL 與回呼 (Callback) URL
- 名稱:
Auth.js + Prisma(或任何您想要的名稱) - 首頁 URL:
https://:3000 - 回呼 URL:
https://:3000/api/auth/callback/github
- 點擊
Register application - 點擊
Generate new client secret並複製Client ID與Client Secret。 - 將
Client ID與Client Secret新增至.env檔案
DATABASE_URL=<YOUR_DATABASE_URL>
AUTH_SECRET=<YOUR_AUTH_SECRET>
AUTH_GITHUB_ID=<YOUR_GITHUB_CLIENT_ID>
AUTH_GITHUB_SECRET=<YOUR_GITHUB_CLIENT_SECRET>
3.3. 設定 Auth.js
在 /lib 資料夾中,建立一個名為 auth.ts 的新檔案,並新增以下程式碼
import NextAuth from 'next-auth'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [],
})
接下來,您需要在 auth.ts 檔案中新增 Github 提供者
import NextAuth from 'next-auth'
import GitHub from 'next-auth/providers/github'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [GitHub],
})
使用者現在將能夠使用 Github 登入。要將他們新增至您的資料庫,您需要使用 Prisma Adapter
import NextAuth from 'next-auth'
import { PrismaAdapter } from '@auth/prisma-adapter'
import prisma from '@/lib/prisma'
import GitHub from 'next-auth/providers/github'
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [GitHub],
})
在根目錄中,建立一個名為 middleware.ts 的新檔案。這將保護您的路由,並確保只有經過驗證的使用者才能存取它們
export { auth as middleware } from '@/lib/auth'
3.4. 設定路由
路由處理器是處理來自 Auth.js 的驗證請求所必需的。它匯出了 Auth.js 用於登入、登出與回呼操作的 GET 與 POST 處理器。
在 app/api/auth/[...nextauth]/route.ts 建立一個新檔案
mkdir -p app/api/auth/[...nextauth]
touch app/api/auth/[...nextauth]/route.ts
將以下程式碼新增至該檔案
import { handlers } from '@/lib/auth'
export const { GET, POST } = handlers
就是這樣!您的應用程式現在已受到保護。要查看更多設定選項,請查閱 Auth.js Middleware 文件。
4. 驗證元件
您將建立登入與登出按鈕。在根目錄建立一個 /components 資料夾,並在其中新增一個名為 auth-components.tsx 的新檔案。
首先從 auth 檔案匯入 signIn 與 signOut 函式
import { signIn, signOut } from "@/lib/auth"
接下來,建立 SignIn 與 SignOut 元件
import { signIn, signOut } from "@/lib/auth"
export function SignIn({ provider }: { provider?: string }) {
return (
<form>
<button className="bg-neutral-700 text-white p-2 rounded-md">
Sign In with {provider}
</button>
</form>
)
}
export function SignOut() {
return (
<form>
<button className="bg-neutral-700 text-white p-2 rounded-md">
Sign Out
</button>
</form>
)
}
要為這兩個按鈕增加功能,請在表單中新增一個動作,分別呼叫 signIn 與 signOut 函式
import { signIn, signOut } from "@/lib/auth"
export function SignIn({ provider }: { provider?: string }) {
return (
<form
action={async () => {
"use server"
await signIn(provider)
}}
>
<button className="bg-neutral-700 text-white p-2 rounded-md">
Sign In with {provider}
</button>
</form>
)
}
export function SignOut() {
return (
<form
action={async () => {
"use server"
await signOut()
}}
className="w-full"
>
<button className="bg-neutral-700 text-white p-2 rounded-md">
Sign Out
</button>
</form>
)
}
5. 將元件新增至您的應用程式
5.1. 設定基礎頁面結構
在 /app 資料夾中,用以下程式碼取代 page.tsx 檔案
const Page = async () => {
return (
<div className="min-h-screen bg-black flex items-center justify-center p-4">
<div className="bg-neutral-800 rounded-lg p-6 max-w-xl w-full">
<h1 className="text-white text-xl mb-4 text-center">Auth.js + Prisma</h1>
</div>
</div>
);
};
export default Page;
5.2. 新增匯入與驗證檢查
匯入所需的元件並新增連線檢查
import { SignIn, SignOut } from "@/components/auth-components";
import { auth } from "@/lib/auth";
const Page = async () => {
const session = await auth();
return (
<div className="min-h-screen bg-black flex items-center justify-center p-4">
<div className="bg-neutral-800 rounded-lg p-6 max-w-xl w-full">
<h1 className="text-white text-xl mb-4 text-center">Auth.js + Prisma</h1>
</div>
</div>
);
};
export default Page;
5.3. 根據驗證狀態顯示內容
新增邏輯以根據使用者是否已登入顯示不同的內容
import { SignIn, SignOut } from "@/components/auth-components";
import { auth } from "@/lib/auth";
const Page = async () => {
const session = await auth();
return (
<div className="min-h-screen bg-black flex items-center justify-center p-4">
<div className="bg-neutral-800 rounded-lg p-6 max-w-xl w-full">
<h1 className="text-white text-xl mb-4 text-center">Auth.js + Prisma</h1>
{!session ? (
<div className="text-center">
<SignIn provider="github" />
</div>
) : (
<div className="space-y-4">
<div className="text-center">
<p className="text-gray-300">Signed in as:</p>
<p className="text-white">{session.user?.email}</p>
</div>
<div className="text-center">
<p className="text-gray-300">Data fetched from DB with Prisma:</p>
</div>
<div className="text-center">
<SignOut />
</div>
</div>
)}
</div>
</div>
);
};
export default Page;
5.4. 將使用者資料新增至頁面
如果使用者已登入,您可以從資料庫獲取使用者資料並將其顯示在頁面上。
import { SignIn, SignOut } from "@/components/auth-components";
import { auth } from "@/lib/auth";
import prisma from "@/lib/prisma";
const Page = async () => {
const session = await auth();
let user = null;
if (session) {
user = await prisma.user.findUnique({
where: {
id: session.user?.id,
}
});
}
return (
<div className="min-h-screen bg-black flex items-center justify-center p-4">
<div className="bg-neutral-800 rounded-lg p-6 max-w-xl w-full">
<h1 className="text-white text-xl mb-4 text-center">Auth.js + Prisma</h1>
{!session ? (
<div className="text-center">
<SignIn provider="github" />
</div>
) : (
<div className="space-y-4">
<div className="text-center">
<p className="text-gray-300">Signed in as:</p>
<p className="text-white">{session.user?.email}</p>
</div>
<div className="text-center">
<p className="text-gray-300">Data fetched from DB with Prisma:</p>
</div>
<div className="bg-neutral-900 rounded p-3">
<pre className="text-xs text-gray-300">
{JSON.stringify(user, null, 2)}
</pre>
</div>
<div className="text-center">
<SignOut />
</div>
</div>
)}
</div>
</div>
);
};
export default Page;
6. 測試應用程式
在啟動開發伺服器之前,請注意如果您使用的是 Next.js v15.2.0 或 v15.2.1,請勿使用 Turbopack,因為存在一個已知的問題。請透過更新您的 package.json 從開發指令中移除 Turbopack
"script":{
"dev": "next dev --turbopack",
"dev": "next dev",
}
在之前或之後的任何版本中都不需要此變更。
您的應用程式現在已完全設定完成。
- 啟動開發伺服器進行測試
npm run dev
-
在瀏覽器中導覽至
https://:3000。您應該會看到包含「Sign In with github」按鈕的首頁。 -
點擊 Sign In with github,授權應用程式,您應該會被重新導向至儀表板。隨後您可以登出並重新登入。
-
要直接在資料庫中檢視使用者資料,您可以使用 Prisma Studio
npx prisma studio
- 這會在您的瀏覽器中開啟一個新分頁,您可以在那裡看到
User、Session和Account表格及其內容。
恭喜!您現在已經擁有了一個由 Auth.js、Prisma 與 Next.js 建構且功能完整的驗證系統。
與 Prisma 保持聯繫
透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作
- 在 X 上關注我們 以獲取公告、現場活動和實用技巧。
- 加入我們的 Discord 提出問題、與社群對話,並透過對話獲得積極支援。
- 在 YouTube 上訂閱 查看教學、演示和直播。
- 在 GitHub 上交流 透過為存放庫加星標、報告問題或為 issue 做出貢獻。