# Auth.js (with Next.js) (/docs/guides/authentication/authjs/nextjs)

Location: Guides > Authentication > Authjs > Auth.js (with Next.js)

Introduction [#introduction]

[Auth.js](https://authjs.dev/) 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](https://nextjs.org/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/authjs-nextjs).

Prerequisites [#prerequisites]

* [Node.js 20+](https://nodejs.org)
* Basic familiarity with Next.js App Router and Prisma

1. Set up your project [#1-set-up-your-project]

Create a new Next.js application:

  

#### npm

```bash
npx create-next-app@latest authjs-prisma
```

#### pnpm

```bash
pnpm dlx create-next-app@latest authjs-prisma
```

#### yarn

```bash
yarn dlx create-next-app@latest authjs-prisma
```

#### bun

```bash
bunx --bun create-next-app@latest authjs-prisma
```

It will prompt you to customize your setup. Choose the defaults:

> [!NOTE]
> * *Would you like to use TypeScript?* `Yes`
> * *Would you like to use ESLint?* `Yes`
> * *Would you like to use Tailwind CSS?* `Yes`
> * *Would you like your code inside a `src/` directory?* `No`
> * *Would you like to use App Router?* (recommended) `Yes`
> * *Would you like to use Turbopack for `next dev`?* `Yes`
> * \_Would you like to customize the import alias (`@/_`by default)?\*`No`

Navigate to the project directory:

```bash
cd authjs-prisma
```

2. Install and configure Prisma [#2-install-and-configure-prisma]

2.1. Install dependencies [#21-install-dependencies]

To get started with Prisma, you'll need to install a few dependencies:

  

#### npm

```bash
npm install prisma tsx @types/pg --save-dev
```

#### pnpm

```bash
pnpm add prisma tsx @types/pg --save-dev
```

#### yarn

```bash
yarn add prisma tsx @types/pg --dev
```

#### bun

```bash
bun add prisma tsx @types/pg --dev
```

  

#### npm

```bash
npm install @prisma/client @prisma/adapter-pg dotenv pg
```

#### pnpm

```bash
pnpm add @prisma/client @prisma/adapter-pg dotenv pg
```

#### yarn

```bash
yarn add @prisma/client @prisma/adapter-pg dotenv pg
```

#### bun

```bash
bun add @prisma/client @prisma/adapter-pg dotenv pg
```

> [!NOTE]
> If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/orm/core-concepts/supported-databases/database-drivers).

Once installed, initialize Prisma in your project:

  

#### npm

```bash
npx prisma init --output ../app/generated/prisma
```

#### pnpm

```bash
pnpm dlx prisma init --output ../app/generated/prisma
```

#### yarn

```bash
yarn dlx prisma init --output ../app/generated/prisma
```

#### bun

```bash
bunx --bun prisma init --output ../app/generated/prisma
```

> [!NOTE]
> `prisma init` creates the Prisma scaffolding and a local `DATABASE_URL`. In the next step, you will create a Prisma Postgres database and replace that value with a direct `postgres://...` connection string.

This will create:

* A `prisma` directory with a `schema.prisma` file.
* A `prisma.config.ts` file for configuring Prisma
* A `.env` file containing a local `DATABASE_URL` at the project root.
* A schema configuration that specifies where the Prisma Client will be generated (`../app/generated/prisma`).

Create a Prisma Postgres database and replace the generated `DATABASE_URL` in your `.env` file with the `postgres://...` connection string from the CLI output:

  

#### npm

```bash
npx create-db
```

#### pnpm

```bash
pnpm dlx create-db
```

#### yarn

```bash
yarn dlx create-db
```

#### bun

```bash
bunx --bun create-db
```

2.2. Define your Prisma Schema [#22-define-your-prisma-schema]

In the `prisma/schema.prisma` file, swap the provider to `prisma-client` and add the runtime `vercel-edge` to the generator:

```prisma title="prisma/schema.prisma"
generator client {
  provider = "prisma-client"
  output   = "../app/generated/prisma"
  runtime  = "vercel-edge" // [!code ++]
}

datasource db {
  provider = "postgresql"
}
```

Add the following models to the `schema.prisma` file, these models are provided by Auth.js:

```prisma title="prisma/schema.prisma"
model Account { // [!code ++]
  id                String  @id @default(cuid()) // [!code ++]
  userId            String  @map("user_id") // [!code ++]
  type              String // [!code ++]
  provider          String // [!code ++]
  providerAccountId String  @map("provider_account_id") // [!code ++]
  refresh_token     String? @db.Text // [!code ++]
  access_token      String? @db.Text // [!code ++]
  expires_at        Int? // [!code ++]
  token_type        String? // [!code ++]
  scope             String? // [!code ++]
  id_token          String? @db.Text // [!code ++]
  session_state     String? // [!code ++]
 // [!code ++]
  user User @relation(fields: [userId], references: [id], onDelete: Cascade) // [!code ++]
 // [!code ++]
  @@unique([provider, providerAccountId]) // [!code ++]
  @@map("accounts") // [!code ++]
} // [!code ++]
 // [!code ++]
model Session { // [!code ++]
  id           String   @id @default(cuid()) // [!code ++]
  sessionToken String   @unique @map("session_token") // [!code ++]
  userId       String   @map("user_id") // [!code ++]
  expires      DateTime // [!code ++]
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade) // [!code ++]
 // [!code ++]
  @@map("sessions") // [!code ++]
} // [!code ++]
 // [!code ++]
model User { // [!code ++]
  id            String    @id @default(cuid()) // [!code ++]
  name          String? // [!code ++]
  email         String?   @unique // [!code ++]
  emailVerified DateTime? @map("email_verified") // [!code ++]
  image         String? // [!code ++]
  accounts      Account[] // [!code ++]
  sessions      Session[] // [!code ++]
 // [!code ++]
  @@map("users") // [!code ++]
} // [!code ++]
 // [!code ++]
model VerificationToken { // [!code ++]
  identifier String // [!code ++]
  token      String // [!code ++]
  expires    DateTime // [!code ++]
 // [!code ++]
  @@unique([identifier, token]) // [!code ++]
  @@map("verification_tokens") // [!code ++]
} // [!code ++]
```

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 Add dotenv to prisma.config.ts [#23-add-dotenv-to-prismaconfigts]

To get access to the variables in the `.env` file, they can either be loaded by your runtime, or by using `dotenv`.
Include an import for `dotenv` at the top of the `prisma.config.ts`

```ts
import "dotenv/config"; // [!code ++]
import { defineConfig, env } from "prisma/config";
export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
  },
  datasource: {
    url: env("DATABASE_URL"),
  },
});
```

2.4. Configure the Prisma Client generator [#24-configure-the-prisma-client-generator]

Now, run the following command to create the database tables and generate the Prisma Client:

  

#### npm

```bash
npx prisma migrate dev --name init
```

#### pnpm

```bash
pnpm dlx prisma migrate dev --name init
```

#### yarn

```bash
yarn dlx prisma migrate dev --name init
```

#### bun

```bash
bunx --bun prisma migrate dev --name init
```

  

#### npm

```bash
npx prisma generate
```

#### pnpm

```bash
pnpm dlx prisma generate
```

#### yarn

```bash
yarn dlx prisma generate
```

#### bun

```bash
bunx --bun prisma generate
```

2.5 Create a Prisma Client [#25-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:

```typescript title="lib/prisma.ts" showLineNumbers
import { PrismaClient } from "../app/generated/prisma/client"; // [!code ++]
import { PrismaPg } from "@prisma/adapter-pg"; // [!code ++]
// [!code ++]
const adapter = new PrismaPg({
  // [!code ++]
  connectionString: process.env.DATABASE_URL!, // [!code ++]
}); // [!code ++]
// [!code ++]
const globalForPrisma = global as unknown as {
  // [!code ++]
  prisma: PrismaClient; // [!code ++]
}; // [!code ++]
// [!code ++]
const prisma =
  globalForPrisma.prisma ||
  new PrismaClient({
    // [!code ++]
    adapter, // [!code ++]
  }); // [!code ++]
// [!code ++]
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; // [!code ++]
// [!code ++]
export default prisma; // [!code ++]
```

3. Set up Auth.js credentials [#3-set-up-authjs-credentials]

3.1. Install dependencies [#31-install-dependencies]

Install the Auth.js dependencies:

  

#### npm

```bash
npm install @auth/prisma-adapter next-auth@beta
```

#### pnpm

```bash
pnpm add @auth/prisma-adapter next-auth@beta
```

#### yarn

```bash
yarn add @auth/prisma-adapter next-auth@beta
```

#### bun

```bash
bun add @auth/prisma-adapter next-auth@beta
```

3.2 Credentials [#32-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:

  

#### npm

```bash
npx auth secret --copy
```

#### pnpm

```bash
pnpm dlx auth secret --copy
```

#### yarn

```bash
yarn dlx auth secret --copy
```

#### bun

```bash
bunx --bun auth secret --copy
```

* `--copy` will copy the secret to your clipboard. *(Normally, just running `npx 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:

```bash title=".env"
DATABASE_URL=<YOUR_DATABASE_URL>
AUTH_SECRET=<YOUR_AUTH_SECRET> # [!code ++]
```

To get the `CLIENT_ID` and `CLIENT_SECRET`, you can create a new OAuth application on Github.

1. Navigate to [Github Developer Settings](https://github.com/settings/developers)
2. Click on `New OAuth App`
3. Enter a name for your app, a home page URL, and a callback URL

* Name: `Auth.js + Prisma` (Or anything you want)
* Homepage URL: `http://localhost:3000`
* Callback URL: `http://localhost:3000/api/auth/callback/github`

4. Click `Register application`
5. Click `Generate new client secret` and copy the `Client ID` and `Client Secret`.
6. Add the `Client ID` and `Client Secret` to the `.env` file:

```bash title=".env"
DATABASE_URL=<YOUR_DATABASE_URL>
AUTH_SECRET=<YOUR_AUTH_SECRET>
AUTH_GITHUB_ID=<YOUR_GITHUB_CLIENT_ID> # [!code ++]
AUTH_GITHUB_SECRET=<YOUR_GITHUB_CLIENT_SECRET> # [!code ++]
```

3.3. Configure Auth.js [#33-configure-authjs]

In the `/lib` folder, create a new file called `auth.ts` and add the following code:

```typescript title="lib/auth.ts"
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:

```typescript title="lib/auth.ts"
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github"; // [!code ++]

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [GitHub], // [!code highlight]
});
```

Users will now be able to sign in with Github. To add them to your database, you'll need to use the [Prisma Adapter](https://authjs.dev/getting-started/adapters/prisma):

```typescript title="lib/auth.ts"
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter"; // [!code ++]
import prisma from "@/lib/prisma"; // [!code ++]
import GitHub from "next-auth/providers/github";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma), // [!code highlight]
  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:

```tsx title="middleware.ts"
export { auth as middleware } from "@/lib/auth";
```

3.4. Configure the Route [#34-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.

Create a new file at `app/api/auth/[...nextauth]/route.ts`:

```bash
mkdir -p app/api/auth/[...nextauth]
touch app/api/auth/[...nextauth]/route.ts
```

Add the following code to the file:

```tsx title="app/api/auth/[...nextauth]/route.ts"
import { handlers } from "@/lib/auth";

export const { GET, POST } = handlers;
```

That's it! Your app is now secured. To see more configuration options, check out the [Auth.js Middleware documentation](https://next-auth.js.org/configuration/nextjs#middleware).

4. Auth components [#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:

```tsx title="components/auth-components.tsx"
import { signIn, signOut } from "@/lib/auth"; // [!code ++]
```

Next, create the `SignIn` and `SignOut` components:

```tsx title="components/auth-components.tsx"
import { signIn, signOut } from "@/lib/auth";

export function SignIn({ provider }: { provider?: string }) {
  // [!code ++]
  return (
    // [!code ++]
    <form>
      {" "}
      // [!code ++]
      <button className="bg-neutral-700 text-white p-2 rounded-md">
        {" "}
        // [!code ++] Sign In with {provider} // [!code ++]
      </button>{" "}
      // [!code ++]
    </form> // [!code ++]
  ); // [!code ++]
} // [!code ++]
// [!code ++]
export function SignOut() {
  // [!code ++]
  return (
    // [!code ++]
    <form>
      {" "}
      // [!code ++]
      <button className="bg-neutral-700 text-white p-2 rounded-md">
        {" "}
        // [!code ++] Sign Out // [!code ++]
      </button>{" "}
      // [!code ++]
    </form> // [!code ++]
  ); // [!code ++]
} // [!code ++]
```

To add functionality to both of the buttons, add an action to the form that calls the `signIn` and `signOut` functions respectively:

```tsx title="components/auth-components.tsx"
import { signIn, signOut } from "@/lib/auth";

export function SignIn({ provider }: { provider?: string }) {
  return (
    <form
      action={async () => {
        // [!code ++]
        "use server"; // [!code ++]
        await signIn(provider); // [!code ++]
      }} // [!code ++]
    >
      <button className="bg-neutral-700 text-white p-2 rounded-md">Sign In with {provider}</button>
    </form>
  );
}

export function SignOut() {
  return (
    <form
      action={async () => {
        // [!code ++]
        "use server"; // [!code ++]
        await signOut(); // [!code ++]
      }} // [!code ++]
      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-add-the-components-to-your-app]

5.1. Set up the basic page structure [#51-set-up-the-basic-page-structure]

In the `/app` folder, replace the `page.tsx` file with the following code:

```tsx title="app/page.tsx"
const Page = async () => {
  // [!code ++]
  return (
    // [!code ++]
    <div className="min-h-screen bg-black flex items-center justify-center p-4">
      {" "}
      // [!code ++]
      <div className="bg-neutral-800 rounded-lg p-6 max-w-xl w-full">
        {" "}
        // [!code ++]
        <h1 className="text-white text-xl mb-4 text-center">Auth.js + Prisma</h1> // [!code ++]
      </div>{" "}
      // [!code ++]
    </div> // [!code ++]
  ); // [!code ++]
}; // [!code ++]
// [!code ++]
export default Page; // [!code ++]
```

5.2. Add imports and authentication check [#52-add-imports-and-authentication-check]

Import the required components and add session checking:

```tsx title="app/page.tsx"
import { SignIn, SignOut } from "@/components/auth-components"; // [!code ++]
import { auth } from "@/lib/auth"; // [!code ++]

const Page = async () => {
  const session = await auth(); // [!code ++]

  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 [#53-show-content-based-on-auth-state]

Add the logic to show different content based on whether the user is signed in:

```tsx title="app/page.tsx"
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 [#54-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.

```tsx title="app/page.tsx"
import { SignIn, SignOut } from "@/components/auth-components";
import { auth } from "@/lib/auth";
import prisma from "@/lib/prisma"; // [!code ++]

const Page = async () => {
  const session = await auth();
  let user = null; // [!code ++]
  // [!code ++]
  if (session) {
    // [!code ++]
    user = await prisma.user.findUnique({
      // [!code ++]
      where: {
        // [!code ++]
        id: session.user?.id, // [!code ++]
      }, // [!code ++]
    }); // [!code ++]
  } // [!code ++]

  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">
              {" "}
              // [!code ++]
              <pre className="text-xs text-gray-300">
                {" "}
                // [!code ++]
                {JSON.stringify(user, null, 2)} // [!code ++]
              </pre>{" "}
              // [!code ++]
            </div>{" "}
            // [!code ++]
            <div className="text-center">
              <SignOut />
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default Page;
```

6. Test it out [#6-test-it-out]

> [!WARNING]
> 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](https://github.com/vercel/next.js/issues/76497). Remove Turbopack from your dev script by updating your `package.json`
> 
> ```json title="package.json"
> "script":{
>     "dev": "next dev --turbopack", // [!code --]
>     "dev": "next dev", // [!code ++]
> }
> ```
> 
> This change is not needed on any versions before or after.

Your application is now fully configured.

1. Start the development server to test it:

  

#### npm

```bash
npm run dev
```

#### pnpm

```bash
pnpm run dev
```

#### yarn

```bash
yarn dev
```

#### bun

```bash
bun run dev
```

2. Navigate to `http://localhost:3000` in your browser. You should see the home page with a "Sign In with github" button.

3. 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.

4. To view the user data directly in your database, you can use Prisma Studio:

  

#### npm

```bash
npx prisma studio
```

#### pnpm

```bash
pnpm dlx prisma studio
```

#### yarn

```bash
yarn dlx prisma studio
```

#### bun

```bash
bunx --bun prisma studio
```

5. This will open a new tab in your browser where you can see the `User`, `Session`, and `Account` tables and their contents.

> [!TIP]
> Congratulations! You now have a fully functional authentication system built with Auth.js, Prisma, and Next.js.