Database Adapters

An Adapter in NextAuth.js connects your application to whatever database or backend system you want to use to store data for user accounts, sessions, etc.

You do not need to specify an adapter explicitly unless you want to use advanced options such as custom models or schemas, if you want to use the Prisma adapter instead of the default TypeORM adapter, or if you are creating a custom adapter to connect to a database that is not one of the supported databases.

Database Schemas

Configure your database by creating the tables and columns to match the schema expected by NextAuth.js.

TypeORM Adapter

NextAuth.js comes with a default adapter that uses TypeORM so that it can be used with many different databases without any further configuration, you simply add the node module for the database driver you want to use to your project and pass a database connection string to NextAuth.js.

The default adapter is the TypeORM adapter, the following configuration options are exactly equivalent.

database: {
type: 'sqlite',
database: ':memory:',
synchronize: true
}
adapter: Adapters.Default({
type: 'sqlite',
database: ':memory:',
synchronize: true
})
adapter: Adapters.TypeORM.Adapter({
type: 'sqlite',
database: ':memory:',
synchronize: true
})

The tutorial Custom models with TypeORM explains how to extend the built in models and schemas used by the TypeORM adapter. You can use these models in your own code.

tip

The synchronize option in TypeORM will generate SQL that exactly matches the documented schemas for MySQL and Postgres.

However, it should not be enabled against production databases as may cause dataloss if the configured schema does not match the expected schema!

Prisma Adapter

You can also use NextAuth.js with Prisma.

To use this adapter, you need to install Prisma Client and Prisma CLI:

npm i @prisma/client
npm add -D @prisma/cli

Configure your NextAuth.js to use the Prisma adapter:

pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import Adapters from 'next-auth/adapters'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const options = {
providers: [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET
})
],
adapter: Adapters.Prisma.Adapter({ prisma }),
}
export default (req, res) => NextAuth(req, res, options)
tip

While Prisma includes an experimental feature in the migration command that is able to generate SQL from a schema, creating tables and columns using the provided SQL is currently recommended instead as SQL schemas automatically generated by Prisma may differ from the recommended schemas.

Prisma Schema

Create a schema.prisma file similar to this one:

schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model Account {
id Int @default(autoincrement()) @id
compoundId String @unique @map(name: "compound_id")
userId Int @map(name: "user_id")
providerType String @map(name: "provider_type")
providerId String @map(name: "provider_id")
providerAccountId String @map(name: "provider_account_id")
refreshToken String? @map(name: "refresh_token")
accessToken String? @map(name: "access_token")
accessTokenExpires DateTime? @map(name: "access_token_expires")
createdAt DateTime @default(now()) @map(name: "created_at")
updatedAt DateTime @default(now()) @map(name: "updated_at")
@@index([providerAccountId], name: "providerAccountId")
@@index([providerId], name: "providerId")
@@index([userId], name: "userId")
@@map(name: "accounts")
}
model Session {
id Int @default(autoincrement()) @id
userId Int @map(name: "user_id")
expires DateTime
sessionToken String @unique @map(name: "session_token")
accessToken String @unique @map(name: "access_token")
createdAt DateTime @default(now()) @map(name: "created_at")
updatedAt DateTime @default(now()) @map(name: "updated_at")
@@map(name: "sessions")
}
model User {
id Int @default(autoincrement()) @id
name String?
email String? @unique
emailVerified DateTime? @map(name: "email_verified")
image String?
createdAt DateTime @default(now()) @map(name: "created_at")
updatedAt DateTime @default(now()) @map(name: "updated_at")
@@map(name: "users")
}
model VerificationRequest {
id Int @default(autoincrement()) @id
identifier String
token String @unique
expires DateTime
createdAt DateTime @default(now()) @map(name: "created_at")
updatedAt DateTime @default(now()) @map(name: "updated_at")
@@map(name: "verification_requests")
}
note

Set the datasource option appropriately for your database:

schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

Generate Client

Once you have saved your schema, you can run the Prisma CLI to generate the Prisma Client:

npx @prisma/cli generate

Custom Models

You can add properties to the schema and map them to any database colum names you wish, but you should not change the base properties or types defined in the example schema.

The model names themselves can be changed with a configuration option, and the datasource can be changed to anything supported by Prisma.

You can use custom model names by using the modelMapping option (shown here with default values).

pages/api/auth/[...nextauth].js
...
adapter: Adapters.Prisma.Adapter({
prisma,
modelMapping: {
User: 'user',
Account: 'account',
Session: 'session',
VerificationRequest: 'verificationRequest'
}
})
...
tip

If you experience issues with Prisma opening too many database connections in local development mode (e.g. due to Hot Module Reloading) you can use an approach like this when initalising the Prisma Client:

pages/api/auth/[...nextauth].js
let prisma
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient()
} else {
if (!global.prisma) {
global.prisma = new PrismaClient()
}
prisma = global.prisma
}

Custom Adapter

See the tutorial for creating a database adapter for more information on how to create a custom adapter.