@auth/drizzle-adapter
Official Drizzle ORM adapter for Auth.js / NextAuth.js.
Installationβ
- npm
- Yarn
- pnpm
npm install drizzle-orm @auth/drizzle-adapter
npm install drizzle-kit --save-dev
yarn add drizzle-orm @auth/drizzle-adapter
yarn add drizzle-kit --dev
pnpm add drizzle-orm @auth/drizzle-adapter
pnpm add drizzle-kit --save-dev
DrizzleAdapter()β
DrizzleAdapter<SqlFlavor>(db, table?): Adapter
Add the adapter to your pages/api/[...nextauth].ts
next-auth configuration object.
pages/api/auth/[...nextauth].ts
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "./schema"
export default NextAuth({
adapter: DrizzleAdapter(db),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
})
info
If you're using multi-project schemas, you can pass your table function as a second argument
Setupβ
First, create a schema that includes the minimum requirements for a next-auth
adapter. You can select your favorite SQL flavor below and copy it.
Additionally, you may extend the schema from the minimum requirements to suit your needs.
Postgresβ
schema.ts
import {
boolean
timestamp,
pgTable,
text,
primaryKey,
integer
} from "drizzle-orm/pg-core"
import type { AdapterAccount } from '@auth/core/adapters'
export const users = pgTable("user", {
id: text("id").notNull().primaryKey(),
name: text("name"),
email: text("email").notNull(),
emailVerified: timestamp("emailVerified", { mode: "date" }),
image: text("image"),
})
export const accounts = pgTable(
"account",
{
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<AdapterAccount["type"]>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state"),
},
(account) => ({
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
})
)
export const sessions = pgTable("session", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
})
export const verificationTokens = pgTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
export const authenticators = pgTable("authenticator", {
id: text("id").notNull().primaryKey(),
credentialID: text("credentialID").notNull().unique(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerAccountId: text("providerAccountId").notNull(),
credentialPublicKey: text("credentialPublicKey").notNull(),
counter: integer("counter").notNull(),
credentialDeviceType: text("credentialDeviceType").notNull(),
credentialBackedUp: boolean("credentialBackedUp").notNull(),
transports: text("transports"),
})
MySQLβ
schema.ts
import {
int,
timestamp,
mysqlTable,
primaryKey,
varchar,
} from "drizzle-orm/mysql-core"
import type { AdapterAccount } from "@auth/core/adapters"
export const users = mysqlTable("user", {
id: varchar("id", { length: 255 }).notNull().primaryKey(),
name: varchar("name", { length: 255 }),
email: varchar("email", { length: 255 }).notNull(),
emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }).defaultNow(),
image: varchar("image", { length: 255 }),
})
export const accounts = mysqlTable(
"account",
{
userId: varchar("userId", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: varchar("type", { length: 255 }).$type<AdapterAccount["type"]>().notNull(),
provider: varchar("provider", { length: 255 }).notNull(),
providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
refresh_token: varchar("refresh_token", { length: 255 }),
access_token: varchar("access_token", { length: 255 }),
expires_at: int("expires_at"),
token_type: varchar("token_type", { length: 255 }),
scope: varchar("scope", { length: 255 }),
id_token: varchar("id_token", { length: 2048 }),
session_state: varchar("session_state", { length: 255 }),
},
(account) => ({
compoundKey: primaryKey({
columns: [account.provider, account.providerAccountId],
}),
})
)
export const sessions = mysqlTable("session", {
sessionToken: varchar("sessionToken", { length: 255 }).notNull().primaryKey(),
userId: varchar("userId", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
})
export const verificationTokens = mysqlTable(
"verificationToken",
{
identifier: varchar("identifier", { length: 255 }).notNull(),
token: varchar("token", { length: 255 }).notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
export const authenticators = pgTable("authenticator", {
id: varchar("id", { length: 255 }).notNull().primaryKey(),
credentialID: varchar("credentialID", { length: 255 }).notNull().unique(),
userId: varchar("userId", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
credentialPublicKey: varchar("credentialPublicKey", {
length: 255,
}).notNull(),
counter: int("counter").notNull(),
credentialDeviceType: varchar("credentialDeviceType", {
length: 255,
}).notNull(),
credentialBackedUp: boolean("credentialBackedUp").notNull(),
transports: varchar("transports", { length: 255 }),
})
SQLiteβ
schema.ts
import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
import type { AdapterAccount } from "@auth/core/adapters"
export const users = sqliteTable("user", {
id: text("id").notNull().primaryKey(),
name: text("name"),
email: text("email").notNull(),
emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
image: text("image"),
})
export const accounts = sqliteTable(
"account",
{
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<AdapterAccount["type"]>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state"),
},
(account) => ({
compoundKey: primaryKey({
columns: [account.provider, account.providerAccountId],
}),
})
)
export const sessions = sqliteTable("session", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
})
export const verificationTokens = sqliteTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
export const authenticators = sqliteTable("authenticator", {
id: text("id").notNull().primaryKey(),
credentialID: text("credentialID").notNull().unique(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerAccountId: text("providerAccountId").notNull(),
credentialPublicKey: text("credentialPublicKey").notNull(),
counter: integer("counter").notNull(),
credentialDeviceType: text("credentialDeviceType").notNull(),
credentialBackedUp: integer("credentialBackedUp", {
mode: "boolean",
}).notNull(),
transports: text("transports"),
})
Migrating your databaseβ
With your schema now described in your code, you'll need to migrate your database to your schema.
For full documentation on how to run migrations with Drizzle, visit the Drizzle documentation.
Type parametersβ
βͺ SqlFlavor extends SqlFlavorOptions
Parametersβ
βͺ db: SqlFlavor
βͺ table?: TableFn
< SqlFlavor
>
Returnsβ
Adapter