Next.js 14 Auth with Auth.js and Drizzle ORM
Next Auth is a widely-used library within the Next.js ecosystem, designed for managing user authentication and authorization in your application.
In this tutorial, I guide you through the process of integrating Next Auth into your Next.js 14 app, utilizing the Drizzle ORM adapter. Everything will be using Server Actions and Server Components.
This setup will enable users to log in to your app using social sign-in providers such as GitHub, with their user data securely stored in your database via Drizzle ORM.
The instructions are a modified version of what's found on the authjs website: https://authjs.dev/reference/nextjs
Setup
npm install next-auth@beta @auth/core
npm install next-auth@beta @auth/core
npm install next-auth@beta @auth/core
npm install next-auth@beta @auth/core
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
export const authConfig = {
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
export const authConfig = {
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
export const authConfig = {
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
export const authConfig = {
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
AUTH_GITHUB_ID=...
AUTH_GITHUB_SECRET=...
AUTH_SECRET=...
AUTH_GITHUB_ID=...
AUTH_GITHUB_SECRET=...
AUTH_SECRET=...
AUTH_GITHUB_ID=...
AUTH_GITHUB_SECRET=...
AUTH_SECRET=...
AUTH_GITHUB_ID=...
AUTH_GITHUB_SECRET=...
AUTH_SECRET=...
You can generate an AUTH_SECRET
using openssl rand -hex 32
, or just click this button:
Github OAuth
Drizzle
npx drizzle-kit push
npx drizzle-kit push
npx drizzle-kit push
npx drizzle-kit push
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
adapter: DrizzleAdapter(db),
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
adapter: DrizzleAdapter(db),
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
adapter: DrizzleAdapter(db),
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import type { NextAuthConfig } from "next-auth"
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
adapter: DrizzleAdapter(db),
providers: [GitHub],
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import NextAuth, { DefaultSession } from "next-auth"
declare module "next-auth" {
interface Session {
user: {
id: string
} & DefaultSession["user"]
}
}
import NextAuth, { DefaultSession } from "next-auth"
declare module "next-auth" {
interface Session {
user: {
id: string
} & DefaultSession["user"]
}
}
import NextAuth, { DefaultSession } from "next-auth"
declare module "next-auth" {
interface Session {
user: {
id: string
} & DefaultSession["user"]
}
}
import NextAuth, { DefaultSession } from "next-auth"
declare module "next-auth" {
interface Session {
user: {
id: string
} & DefaultSession["user"]
}
}
import NextAuth, { NextAuthConfig } from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
providers: [GitHub],
adapter: DrizzleAdapter(db),
callbacks: {
async session({session, user}) {
session.user.id = user.id
return session
},
}
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import NextAuth, { NextAuthConfig } from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
providers: [GitHub],
adapter: DrizzleAdapter(db),
callbacks: {
async session({session, user}) {
session.user.id = user.id
return session
},
}
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import NextAuth, { NextAuthConfig } from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
providers: [GitHub],
adapter: DrizzleAdapter(db),
callbacks: {
async session({session, user}) {
session.user.id = user.id
return session
},
}
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
import NextAuth, { NextAuthConfig } from "next-auth"
import GitHub from "next-auth/providers/GitHub"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "@/db"
export const authConfig = {
providers: [GitHub],
adapter: DrizzleAdapter(db),
callbacks: {
async session({session, user}) {
session.user.id = user.id
return session
},
}
} satisfies NextAuthConfig
export const {
handlers,
auth,
signOut
} = NextAuth(authConfig)
Usage
import { auth, signOut } from "@/auth"
import { redirect } from "next/navigation"
import SignoutButton from "./sign-out-button"
export default async function ProfilePage() {
const session = await auth()
if (!session?.user) {
redirect("/api/auth/signin?callbackUrl=/me")
}
return (
<>
{session.user.id}
{session.user.name}
{session.user.email}
<Image src={session.user.image} />
<SignoutButton
signOut={async () => {
"use server"
await signOut({redirectTo: "/"})
}}
/>
</>
)
}
import { auth, signOut } from "@/auth"
import { redirect } from "next/navigation"
import SignoutButton from "./sign-out-button"
export default async function ProfilePage() {
const session = await auth()
if (!session?.user) {
redirect("/api/auth/signin?callbackUrl=/me")
}
return (
<>
{session.user.id}
{session.user.name}
{session.user.email}
<Image src={session.user.image} />
<SignoutButton
signOut={async () => {
"use server"
await signOut({redirectTo: "/"})
}}
/>
</>
)
}
import { auth, signOut } from "@/auth"
import { redirect } from "next/navigation"
import SignoutButton from "./sign-out-button"
export default async function ProfilePage() {
const session = await auth()
if (!session?.user) {
redirect("/api/auth/signin?callbackUrl=/me")
}
return (
<>
{session.user.id}
{session.user.name}
{session.user.email}
<Image src={session.user.image} />
<SignoutButton
signOut={async () => {
"use server"
await signOut({redirectTo: "/"})
}}
/>
</>
)
}
import { auth, signOut } from "@/auth"
import { redirect } from "next/navigation"
import SignoutButton from "./sign-out-button"
export default async function ProfilePage() {
const session = await auth()
if (!session?.user) {
redirect("/api/auth/signin?callbackUrl=/me")
}
return (
<>
{session.user.id}
{session.user.name}
{session.user.email}
<Image src={session.user.image} />
<SignoutButton
signOut={async () => {
"use server"
await signOut({redirectTo: "/"})
}}
/>
</>
)
}
Middleware
import NextAuth from 'next-auth';
import { authConfig } from './auth';
export default NextAuth(authConfig).auth;
export const config = {
// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
matcher: ['/((?!api|_next/static|_next/image|.png).*)'],
};
import NextAuth from 'next-auth';
import { authConfig } from './auth';
export default NextAuth(authConfig).auth;
export const config = {
// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
matcher: ['/((?!api|_next/static|_next/image|.png).*)'],
};
import NextAuth from 'next-auth';
import { authConfig } from './auth';
export default NextAuth(authConfig).auth;
export const config = {
// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
matcher: ['/((?!api|_next/static|_next/image|.png).*)'],
};
import NextAuth from 'next-auth';
import { authConfig } from './auth';
export default NextAuth(authConfig).auth;
export const config = {
// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
matcher: ['/((?!api|_next/static|_next/image|.png).*)'],
};
Complete Code
https://github.com/meech-ward/next-auth-example
References
- https://authjs.dev/guides/upgrade-to-v5
- https://next-auth.js.org/getting-started/rest-api
- https://authjs.dev/reference/adapter/drizzle
- https://next-auth.js.org/configuration/callbacks#session-callback
- https://next-auth.js.org/getting-started/typescript
- https://next-auth.js.org/configuration/callbacks
- https://github.com/nextauthjs/next-auth/issues/535#issuecomment-668576271
- https://authjs.dev/getting-started/adapters#user