How to use Prisma ORM with Auth.js and Next.js
介绍
¥Introduction
Auth.js is a flexible, open-source authentication library designed to simplify adding authentication to your Next.js applications.
In this guide, you'll wire Auth.js into a brand-new Next.js app and persist users in a Prisma Postgres database.你可以在 GitHub 上找到本指南的完整示例。
¥In this guide, you'll wire Auth.js into a brand-new Next.js app and persist users in a Prisma Postgres database. You can find a complete example of this guide on GitHub.
先决条件
¥Prerequisites
-
熟悉 Next.js 应用路由和 Prisma
¥Basic familiarity with Next.js App Router and Prisma
1. 设置你的项目
¥ Set up your project
创建一个新的 Next.js 应用:
¥Create a new Next.js application:
npx create-next-app@latest authjs-prisma
它会提示你自定义设置。选择默认值:
¥It will prompt you to customize your setup. Choose the defaults:
-
你想使用 TypeScript 吗?
Yes
¥Would you like to use TypeScript?
Yes
-
你想使用 ESLint 吗?
Yes
¥Would you like to use ESLint?
Yes
-
你想使用 Tailwind CSS 吗?
Yes
¥Would you like to use Tailwind CSS?
Yes
-
你想将代码放在
src/
目录中吗?No
¥Would you like your code inside a
src/
directory?No
-
你想使用 App Router 吗?(推荐)
Yes
¥Would you like to use App Router? (recommended)
Yes
-
你想为
next dev
使用 Turbopack 吗?Yes
¥Would you like to use Turbopack for
next dev
?Yes
-
你想自定义导入别名(默认为
@/*
)吗?No
¥Would you like to customize the import alias (
@/*
by default)?No
导航到项目目录:
¥Navigate to the project directory:
cd authjs-prisma
2. 安装和配置 Prisma
¥ Install and configure Prisma
2.1.安装依赖
¥2.1. Install dependencies
要开始使用 Prisma,你需要安装一些依赖:
¥To get started with Prisma, you'll need to install a few dependencies:
- Prisma Postgres (recommended)
- Other databases
npm install prisma tsx --save-dev
npm install @prisma/extension-accelerate @prisma/client
npm install prisma tsx --save-dev
npm install @prisma/client
安装完成后,请在你的项目中初始化 Prisma:
¥Once installed, initialize Prisma in your project:
npx prisma init --db --output ../app/generated/prisma
在设置 Prisma Postgres 数据库时,你需要回答几个问题。选择离你最近的区域,并为数据库选择一个容易记住的名称,例如 "My Auth.js Project"
¥You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Auth.js Project"
这将造成:
¥This will create:
-
一个包含
schema.prisma
文件的prisma
目录。¥A
prisma
directory with aschema.prisma
file. -
一个 Prisma Postgres 数据库。
¥A Prisma Postgres database.
-
一个位于项目根目录、包含
DATABASE_URL
文件的.env
文件。¥A
.env
file containing theDATABASE_URL
at the project root. -
A schema configuration that specifies where the Prisma Client will be generated (
../app/generated/prisma
).
2.2.定义 Prisma Schema
¥2.2. Define your Prisma Schema
In the prisma/schema.prisma
file, swap the provider to prisma-client
and add the runtime edge-light
to the generator:
generator client {
provider = "prisma-client"
output = "../app/generated/prisma"
runtime = "edge-light"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Add the following models to the schema.prisma
file, these models are provided by 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")
}
This creates the following models:
-
Account
:Stores OAuth provider information (access tokens, refresh tokens, provider account IDs) and enables users to sign in with multiple providers while maintaining a single user record. -
Session
:Tracks authenticated user sessions with a unique session token, user ID, and expiration time to maintain authentication state across requests. -
User
:The core model storing user information (name, email, profile image).Users can have multiple accounts from different providers and multiple active sessions. -
VerificationToken
:Stores temporary tokens for email verification, password reset, and other security operations with expiration times.
2.3.配置 Prisma 客户端生成器
¥2.3. Configure the Prisma Client generator
现在,运行以下命令创建数据库表并生成 Prisma 客户端:
¥Now, run the following command to create the database tables and generate the Prisma Client:
npx prisma migrate dev --name init
2.4 Create a Prisma Client
Create a new folder in the root called lib
and create a new file called prisma.ts
in it.This file will contain the Prisma Client:
- Prisma Postgres (recommended)
- Other databases
import { PrismaClient } from '../app/generated/prisma'
import { withAccelerate } from '@prisma/extension-accelerate'
const globalForPrisma = global as unknown as {
prisma: PrismaClient
}
const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate())
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
import { PrismaClient } from '../app/generated/prisma'
const globalForPrisma = global as unknown as {
prisma: PrismaClient
}
const prisma = globalForPrisma.prisma || new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
3. Set up Auth.js credentials
3.1.安装依赖
¥3.1. Install dependencies
Install the Auth.js dependencies:
npm install @auth/prisma-adapter next-auth@beta
3.2 Credentials
For this guide, you'll be setting up OAuth with Github.For this, you'll need 3 environment variables:
-
AUTH_SECRET
- Provided by Auth.js -
CLIENT_ID
- Provided by Github -
CLIENT_SECRET
- Provided by Github
To get the AUTH_SECRET
, you can run the following command:
npx auth secret --copy
--copy
will copy the secret to your clipboard.(Normally, just runningnpx auth secret
will add the secret to your.env.local
file. To keep it tidy, you can use--copy
and add it to the.env
file that Prisma created earlier.)
Add the following to the .env
file:
DATABASE_URL=<YOUR_DATABASE_URL>
AUTH_SECRET=<YOUR_AUTH_SECRET>
To get the CLIENT_ID
and CLIENT_SECRET
, you can create a new OAuth application on Github.
- Navigate to Github Developer Settings
- Click on
New OAuth App
- Enter a name for your app, a home page URL, and a callback URL
-
名称:
Auth.js + Prisma
(Or anything you want)¥Name:
Auth.js + Prisma
(Or anything you want) -
Homepage URL:
http://localhost:3000
-
回调 URL:
http://localhost:3000/api/auth/callback/github
¥Callback URL:
http://localhost:3000/api/auth/callback/github
-
点击“
Register application
ӴClick
Register application
-
Click
Generate new client secret
and copy theClient ID
andClient Secret
. -
Add the
Client ID
andClient Secret
to the.env
file:
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.Configure Auth.js
In the /lib
folder, create a new file called auth.ts
and add the following code:
import NextAuth from 'next-auth'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [],
})
Next, you'll need to add the Github provider to the auth.ts
file:
import NextAuth from 'next-auth'
import GitHub from 'next-auth/providers/github'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [GitHub],
})
Users will now be able to sign in with Github.To add them to your database, you'll need to use the 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],
})
In the root, create a new file called middleware.ts
.This will protect your routes and ensure that only authenticated users can access them:
export { auth as middleware } from '@/lib/auth'
3.4.Configure the Route
The route handler is required to handle authentication requests from Auth.js.It exports the GET
and POST
handlers that Auth.js uses for sign-in, sign-out, and callback operations.
在 app/api/auth/[...nextauth]/route.ts
目录下创建一个新文件:
¥Create a new file at app/api/auth/[...nextauth]/route.ts
:
mkdir -p app/api/auth/[...nextauth]
touch app/api/auth/[...nextauth]/route.ts
Add the following code to the file:
import { handlers } from '@/lib/auth'
export const { GET, POST } = handlers
就是这样!Your app is now secured.To see more configuration options, check out the Auth.js Middleware documentation.
¥That's it! Your app is now secured. To see more configuration options, check out the Auth.js Middleware documentation.
4. Auth components
You will be creating a Sign In and Sign Out button.Create a /components
folder in the root and add a new file called auth-components.tsx
in it.
Start by importing the signIn
and signOut
functions from the auth
file:
import { signIn, signOut } from "@/lib/auth"
Next, create the SignIn
and SignOut
components:
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>
)
}
To add functionality to both of the buttons, add an action to the form that calls the signIn
and signOut
functions respectively:
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. Add the components to your app
5.1.Set up the basic page structure
In the /app
folder, replace the page.tsx
file with the following code:
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.Add imports and authentication check
Import the required components and add session checking:
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.Show content based on auth state
Add the logic to show different content based on whether the user is signed in:
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.Add the user data to the page
If the user is signed in, you can fetch the user data from the database and display it on the page.
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. 测试一下
¥ Test it out
在启动开发服务器之前,请注意,如果你使用的是 Next.js v15.2.0 或 v15.2.1,请勿使用 Turbopack,因为存在已知的 issue。通过更新你的 package.json
脚本,从你的开发脚本中移除 Turbopack
¥Before starting the development server, note that if you are using Next.js v15.2.0 or v15.2.1, do not use Turbopack as there is a known issue. Remove Turbopack from your dev script by updating your package.json
"script":{
"dev": "next dev --turbopack",
"dev": "next dev",
}
此更改在之前或之后的任何版本中都不需要。
¥This change is not needed on any versions before or after.
你的应用现已完全配置。
¥Your application is now fully configured.
-
启动开发服务器进行测试:
¥Start the development server to test it:
npm run dev
-
在浏览器中导航到
http://localhost:3000
。You should see the home page with a "Sign In with github" button.¥Navigate to
http://localhost:3000
in your browser. You should see the home page with a "Sign In with github" button. -
Click on Sign In with github, authorize the app, and you should be redirected to the dashboard.然后你可以退出并重新登录。
¥Click on Sign In with github, authorize the app, and you should be redirected to the dashboard. You can then sign out and sign back in.
-
To view the user data directly in your database, you can use Prisma Studio:
npx prisma studio
-
这将在你的浏览器中打开一个新标签页,你可以在其中查看
User
、Session
和Account
表及其内容。¥This will open a new tab in your browser where you can see the
User
,Session
, andAccount
tables and their contents.
恭喜!You now have a fully functional authentication system built with Auth.js, Prisma, and Next.js.
¥Congratulations! You now have a fully functional authentication system built with Auth.js, Prisma, and Next.js.
Stay connected with Prisma
Continue your Prisma journey by connecting with our active community. Stay informed, get involved, and collaborate with other developers:
- Follow us on X for announcements, live events and useful tips.
- Join our Discord to ask questions, talk to the community, and get active support through conversations.
- Subscribe on YouTube for tutorials, demos, and streams.
- Engage on GitHub by starring the repository, reporting issues, or contributing to an issue.