TypeORM Adapter
Resources
Setup
Installation
npm install @auth/typeorm-adapter typeorm
Environment Variables
AUTH_TYPEORM_CONNECTION=postgres://postgres:adminadmin@0.0.0.0:5432/db
Configuration
import NextAuth from "next-auth"
import { TypeORMAdapter } from "@auth/typeorm-adapter"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: TypeORMAdapter(process.env.AUTH_TYPEORM_CONNECTION),
})
TypeORMAdapter
takes either a connection string, or a ConnectionOptions
object as its first parameter.
Advanced usage
Custom models
The TypeORM adapter uses Entity
classes to define the shape of your data.
You can override the default entities and add additional fields with a custom entities file.
- Create a file containing your modified entities:
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
OneToMany,
ValueTransformer,
} from "typeorm"
const transformer: Record<"date" | "bigint", ValueTransformer> = {
date: {
from: (date: string | null) => date && new Date(parseInt(date, 10)),
to: (date?: Date) => date?.valueOf().toString(),
},
bigint: {
from: (bigInt: string | null) => bigInt && parseInt(bigInt, 10),
to: (bigInt?: number) => bigInt?.toString(),
},
}
@Entity({ name: "users" })
export class UserEntity {
@PrimaryGeneratedColumn("uuid")
id!: string
@Column({ type: "varchar", nullable: true })
name!: string | null
@Column({ type: "varchar", nullable: true, unique: true })
email!: string | null
@Column({ type: "varchar", nullable: true, transformer: transformer.date })
emailVerified!: string | null
@Column({ type: "varchar", nullable: true })
image!: string | null
+ @Column({ type: "varchar", nullable: true })
+ role!: string | null
@OneToMany(() => SessionEntity, (session) => session.userId)
sessions!: SessionEntity[]
@OneToMany(() => AccountEntity, (account) => account.userId)
accounts!: AccountEntity[]
}
@Entity({ name: "accounts" })
export class AccountEntity {
@PrimaryGeneratedColumn("uuid")
id!: string
@Column({ type: "uuid" })
userId!: string
@Column()
type!: string
@Column()
provider!: string
@Column()
providerAccountId!: string
@Column({ type: "varchar", nullable: true })
refresh_token!: string | null
@Column({ type: "varchar", nullable: true })
access_token!: string | null
@Column({
nullable: true,
type: "bigint",
transformer: transformer.bigint,
})
expires_at!: number | null
@Column({ type: "varchar", nullable: true })
token_type!: string | null
@Column({ type: "varchar", nullable: true })
scope!: string | null
@Column({ type: "varchar", nullable: true })
id_token!: string | null
@Column({ type: "varchar", nullable: true })
session_state!: string | null
@Column({ type: "varchar", nullable: true })
oauth_token_secret!: string | null
@Column({ type: "varchar", nullable: true })
oauth_token!: string | null
@ManyToOne(() => UserEntity, (user) => user.accounts, {
createForeignKeyConstraints: true,
})
user!: UserEntity
}
@Entity({ name: "sessions" })
export class SessionEntity {
@PrimaryGeneratedColumn("uuid")
id!: string
@Column({ unique: true })
sessionToken!: string
@Column({ type: "uuid" })
userId!: string
@Column({ transformer: transformer.date })
expires!: string
@ManyToOne(() => UserEntity, (user) => user.sessions)
user!: UserEntity
}
@Entity({ name: "verification_tokens" })
export class VerificationTokenEntity {
@PrimaryGeneratedColumn("uuid")
id!: string
@Column()
token!: string
@Column()
identifier!: string
@Column({ transformer: transformer.date })
expires!: string
}
- Pass them to
TypeORMAdapter
import NextAuth from "next-auth"
import { TypeORMAdapter } from "@auth/typeorm-adapter"
import * as entities from "lib/entities"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: TypeORMAdapter("yourconnectionstring", { entities }),
})
The synchronize: true
option in TypeORM will generate SQL that exactly
matches the entities. This will automatically apply any changes it finds in
the entity model. This is a useful option in development.
synchronize: true
should not be enabled against production databases as it
may cause data loss if the configured schema does not match the expected
schema! We recommend that you synchronize/migrate your production database at
build-time.
Naming Conventions
If mixed snake_case and camelCase column names are an issue for you and/or your underlying database system, we recommend using TypeORM’s naming strategy feature to change the target field names. There is a package called typeorm-naming-strategies
which includes a snake_case
strategy which will translate the fields from how Auth.js expects them, to snake_case in the actual database.
For example, you can add the naming convention option to the connection object in your NextAuth config.
import NextAuth from "next-auth"
import { TypeORMAdapter } from "@auth/typeorm-adapter"
import { SnakeNamingStrategy } from "typeorm-naming-strategies"
import { ConnectionOptions } from "typeorm"
const connection: ConnectionOptions = {
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
namingStrategy: new SnakeNamingStrategy(),
}
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: TypeORMAdapter(connection),
})