@auth/drizzle-adapter
Official Drizzle ORM adapter for Auth.js / NextAuth.js.
Installation
npm install drizzle-orm @auth/drizzle-adapter
npm install drizzle-kit --save-dev
mysqlAccountsTable
Re-exports mysqlAccountsTable
mysqlSessionsTable
Re-exports mysqlSessionsTable
mysqlUsersTable
Re-exports mysqlUsersTable
mysqlVerificationTokensTable
Re-exports mysqlVerificationTokensTable
postgresAccountsTable
Re-exports postgresAccountsTable
postgresSessionsTable
Re-exports postgresSessionsTable
postgresUsersTable
Re-exports postgresUsersTable
postgresVerificationTokensTable
Re-exports postgresVerificationTokensTable
sqliteAccountsTable
Re-exports sqliteAccountsTable
sqliteSessionsTable
Re-exports sqliteSessionsTable
sqliteUsersTable
Re-exports sqliteUsersTable
sqliteVerificationTokensTable
Re-exports sqliteVerificationTokensTable
DrizzleAdapter()
DrizzleAdapter<SqlFlavor>(db, schema?): Adapter
Add this adapter to your auth.ts
Auth.js configuration object:
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "./schema"
export const { handlers, auth } = NextAuth({
adapter: DrizzleAdapter(db),
providers: [
Google,
],
})
If you want to use your own tables, you can pass them as a second argument
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db, accounts, sessions, users, verificationTokens } from "./schema"
export const { handlers, auth } = NextAuth({
adapter: DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens }),
providers: [
Google,
],
})
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
import {
timestamp,
pgTable,
text,
primaryKey,
integer
} from "drizzle-orm/pg-core"
import type { AdapterAccount } from '@auth/core/adapters'
import { randomUUID } from "crypto"
export const users = pgTable("user", {
id: text("id").primaryKey().$defaultFn(() => randomUUID()),
name: text("name"),
email: text("email").notNull().unique(),
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").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) => ({
userIdIdx: index().on(account.userId),
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
})
)
export const sessions = pgTable("session", {
id: text("id").primaryKey().$defaultFn(() => randomUUID()),
sessionToken: text("sessionToken").notNull().unique(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
}, (session) => ({
userIdIdx: index().on(session.userId)
}))
export const verificationTokens = pgTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull().unique(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
MySQL
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 }).primaryKey().$defaultFn(() => randomUUID()),
name: varchar("name", { length: 255 }),
email: varchar("email", { length: 255 }).notNull().unique(),
emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
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 }).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],
}),
userIdIdx: index('Account_userId_index').on(account.userId)
})
)
export const sessions = mysqlTable("session", {
id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => randomUUID()),
sessionToken: varchar("sessionToken", { length: 255 }).notNull().unique(),
userId: varchar("userId", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
}, (session) => ({
userIdIdx: index('Session_userId_index').on(session.userId)
}))
export const verificationTokens = mysqlTable(
"verificationToken",
{
identifier: varchar("identifier", { length: 255 }).notNull(),
token: varchar("token", { length: 255 }).notNull().unique(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
SQLite
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").primaryKey().$defaultFn(() => randomUUID()),
name: text("name"),
email: text("email").notNull().unique(),
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").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],
}),
userIdIdx: index('Account_userId_index').on(account.userId)
})
)
export const sessions = sqliteTable("session", {
id: text("id").primaryKey().$defaultFn(() => randomUUID())
sessionToken: text("sessionToken").notNull().unique(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
}, (table) => ({
userIdIdx: index('Session_userId_index').on(table.userId)
}))
export const verificationTokens = sqliteTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull().unique(),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
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
Type parameter |
---|
SqlFlavor extends SqlFlavorOptions |
Parameters
Parameter | Type |
---|---|
db | SqlFlavor |
schema ? | DefaultSchema <SqlFlavor > |