Home Quizzes Leaderboard Competitions Learn Hire Us
About Contact
Log In Sign Up
Learn Next.js Authentication with NextAuth.js

Authentication with NextAuth.js

⏱ 20 min read read
Setup NextAuth.js v5 (Auth.js):

npm install next-auth@beta

# .env.local

AUTH_SECRET=your-random-secret-here # openssl rand -base64 32

AUTH_GITHUB_ID=your-github-oauth-id

AUTH_GITHUB_SECRET=your-github-secret

// auth.ts --- config file

import NextAuth from 'next-auth';

import GitHub from 'next-auth/providers/github';

import Credentials from 'next-auth/providers/credentials';

export const { handlers, signIn, signOut, auth } = NextAuth({

providers: [

GitHub,

Credentials({

credentials: { email: {}, password: {} },

async authorize({ email, password }) {

const user = await verifyUser(email as string, password as string);

return user ?? null;

},

}),

],

});

// app/api/auth/[...nextauth]/route.ts

export { handlers as GET, handlers as POST } from '@/auth';

Protecting Routes with Middleware:

// middleware.ts (root of project)

export { auth as middleware } from '@/auth';

export const config = {

matcher: ['/dashboard/:path*', '/profile/:path*'],

};

Reading Session Data:

// Server Component

import { auth } from '@/auth';

const session = await auth();

if (!session) redirect('/login');

console.log(session.user?.name);

// Client Component

import { useSession } from 'next-auth/react';

const { data: session, status } = useSession();

if (status === 'loading') return <p>Loading...</p>;

if (status === 'unauthenticated') redirect('/login');

NextAuth.js handles OAuth (GitHub, Google, Discord), credentials,
email magic links.

The session is stored in a signed, encrypted JWT cookie by default.

Adapter packages connect NextAuth to Prisma, Drizzle, etc. for DB
sessions.

Install Prisma adapter: npm install @auth/prisma-adapter
Code Example
// Full example: protected dashboard page

// auth.ts

import NextAuth from 'next-auth';

import GitHub from 'next-auth/providers/github';

export const { handlers, auth, signIn, signOut } = NextAuth({

providers: [GitHub],

pages: { signIn: '/login' },

callbacks: {

session({ session, token }) {

if (token.sub) session.user.id = token.sub;

return session;

},

},

});

// app/dashboard/page.tsx --- protected Server Component

import { auth } from '@/auth';

import { redirect } from 'next/navigation';

export default async function DashboardPage() {

const session = await auth();

if (!session) redirect('/login');

return (

<div>

<h1>Welcome, {session.user?.name}!</h1>

<img src={session.user?.image ?? ''} alt="avatar" width={48}
height={48} />

<p>Email: {session.user?.email}</p>

<form action={async () => { 'use server'; await signOut(); }}>

<button type="submit">Sign out</button>

</form>

</div>

);

}

// app/login/page.tsx

import { signIn } from '@/auth';

export default function LoginPage() {

return (

<main>

<h1>Sign in</h1>

<form action={async () => { 'use server'; await
signIn('github'); }}>

<button type="submit">Sign in with GitHub</button>

</form>

</main>

);

}

// middleware.ts --- protect all /dashboard routes

export { auth as middleware } from '@/auth';

export const config = { matcher: ['/dashboard/:path*'] };
← Databases with Prisma Metadata, SEO & the Head →

Log in to track your progress and earn badges as you complete lessons.

Log In to Track Progress