NextAuth.js (Auth.js)
Authentication patterns for NextAuth.js v5 (Auth.js) in Next.js applications.
Overview#
NextAuth.js provides flexible authentication with:
- Multiple OAuth providers (Google, GitHub, Apple, etc.)
- Database adapters for session persistence
- JWT or database session strategies
- Credentials-based authentication
- TypeScript support
Prerequisites:
- Next.js 14+ with App Router
- Database (optional, for session storage)
Installation#
npm install next-auth @auth/prisma-adapter1# .env.local
2AUTH_SECRET=your-secret-key
3GITHUB_ID=your-github-client-id
4GITHUB_SECRET=your-github-client-secret
5GOOGLE_ID=your-google-client-id
6GOOGLE_SECRET=your-google-client-secretImplementation#
Basic Setup#
1// auth.ts
2import NextAuth from 'next-auth'
3import GitHub from 'next-auth/providers/github'
4import Google from 'next-auth/providers/google'
5import { PrismaAdapter } from '@auth/prisma-adapter'
6import { prisma } from '@/lib/db'
7
8export const { handlers, auth, signIn, signOut } = NextAuth({
9 adapter: PrismaAdapter(prisma),
10 session: { strategy: 'jwt' },
11 providers: [
12 GitHub({
13 clientId: process.env.GITHUB_ID!,
14 clientSecret: process.env.GITHUB_SECRET!
15 }),
16 Google({
17 clientId: process.env.GOOGLE_ID!,
18 clientSecret: process.env.GOOGLE_SECRET!
19 })
20 ],
21 callbacks: {
22 async jwt({ token, user }) {
23 if (user) {
24 token.id = user.id
25 }
26 return token
27 },
28 async session({ session, token }) {
29 if (session.user) {
30 session.user.id = token.id as string
31 }
32 return session
33 }
34 },
35 pages: {
36 signIn: '/login',
37 error: '/login'
38 }
39})Route Handler#
// app/api/auth/[...nextauth]/route.ts
import { handlers } from '@/auth'
export const { GET, POST } = handlersServer-Side Auth Check#
1// lib/auth.ts
2import { auth } from '@/auth'
3
4export async function getSession() {
5 return auth()
6}
7
8export async function requireAuth() {
9 const session = await auth()
10
11 if (!session?.user) {
12 throw new Error('Unauthorized')
13 }
14
15 return session
16}Credentials Provider#
1// auth.ts (add to providers)
2import Credentials from 'next-auth/providers/credentials'
3import bcrypt from 'bcryptjs'
4
5Credentials({
6 credentials: {
7 email: { type: 'email' },
8 password: { type: 'password' }
9 },
10 async authorize(credentials) {
11 const user = await prisma.user.findUnique({
12 where: { email: credentials.email as string }
13 })
14
15 if (!user?.password) return null
16
17 const valid = await bcrypt.compare(
18 credentials.password as string,
19 user.password
20 )
21
22 if (!valid) return null
23
24 return { id: user.id, email: user.email, name: user.name }
25 }
26})Sign In/Out Components#
1// components/auth-buttons.tsx
2'use client'
3import { signIn, signOut } from 'next-auth/react'
4import { Button } from '@/components/ui/button'
5
6export function SignInButton() {
7 return (
8 <Button onClick={() => signIn('github')}>
9 Sign In with GitHub
10 </Button>
11 )
12}
13
14export function SignOutButton() {
15 return (
16 <Button variant="outline" onClick={() => signOut()}>
17 Sign Out
18 </Button>
19 )
20}Usage Examples#
Protected Server Component#
1// app/dashboard/page.tsx
2import { auth } from '@/auth'
3import { redirect } from 'next/navigation'
4
5export default async function DashboardPage() {
6 const session = await auth()
7
8 if (!session) {
9 redirect('/login')
10 }
11
12 return <Dashboard user={session.user} />
13}Client Component with Session#
1// components/user-menu.tsx
2'use client'
3
4import { useSession } from 'next-auth/react'
5
6export function UserMenu() {
7 const { data: session, status } = useSession()
8
9 if (status === 'loading') {
10 return <div>Loading...</div>
11 }
12
13 if (!session) {
14 return <SignInButton />
15 }
16
17 return (
18 <div>
19 <span>{session.user?.name}</span>
20 <SignOutButton />
21 </div>
22 )
23}Best Practices#
- Use JWT strategy for serverless - Database sessions require persistent connections
- Always validate in callbacks - Check email verification status
- Secure credentials flow - Hash passwords with bcrypt, minimum 12 rounds
- Set up session provider - Wrap app in SessionProvider for client access
- Use database adapter - For production, persist sessions and accounts
Related Patterns#
- OAuth - OAuth 2.0 integration details
- Session Management - Session handling patterns
- JWT - JWT token handling