← Back to chapters
13advanced

Authentication (Auth.js)

Protect your app with Auth.js (NextAuth v5). OAuth, credentials, sessions, and guards.

Authentication with Auth.js (NextAuth v5)

Auth is hard. Don't build it from scratch. Auth.js (the new name for NextAuth) handles OAuth, credentials, sessions, JWTs, and more. Here's how to set it up properly in Next.js 15.

⚠️

NextAuth v4 vs Auth.js v5

If you see tutorials using 'next-auth' with api/auth/[...nextauth]/route.ts, that's v4 (old). Auth.js v5 uses a different setup with auth.ts at the root. This guide covers v5.

Installation

Terminal
bash
1npm install next-auth@beta

Setup

src/auth.ts
tsx
1// src/auth.ts
2import NextAuth from "next-auth";
3import GitHub from "next-auth/providers/github";
4import Google from "next-auth/providers/google";
5
6export const { handlers, signIn, signOut, auth } = NextAuth({
7providers: [
8 GitHub({
9 clientId: process.env.GITHUB_ID!,
10 clientSecret: process.env.GITHUB_SECRET!,
11 }),
12 Google({
13 clientId: process.env.GOOGLE_ID!,
14 clientSecret: process.env.GOOGLE_SECRET!,
15 }),
16],
17});
src/app/api/auth/[...nextauth]/route.ts
tsx
1// src/app/api/auth/[...nextauth]/route.ts
2import { handlers } from "@/auth";
3
4export const { GET, POST } = handlers;

Protecting Pages

src/app/dashboard/page.tsx
tsx
1// src/app/dashboard/page.tsx
2import { auth } from "@/auth";
3import { redirect } from "next/navigation";
4
5export default async function DashboardPage() {
6const session = await auth();
7
8if (!session) {
9 redirect("/login");
10}
11
12return (
13 <div>
14 <h1>Welcome, {session.user?.name}</h1>
15 <img src={session.user?.image ?? ""} alt="Avatar" />
16 </div>
17);
18}

Sign In / Sign Out Buttons

src/components/AuthButtons.tsx
tsx
1// src/components/AuthButtons.tsx
2import { signIn, signOut, auth } from "@/auth";
3
4export async function SignInButton() {
5const session = await auth();
6
7if (session) {
8 return (
9 <form action={async () => {
10 "use server";
11 await signOut();
12 }}>
13 <button type="submit">Sign Out</button>
14 </form>
15 );
16}
17
18return (
19 <form action={async () => {
20 "use server";
21 await signIn("github");
22 }}>
23 <button type="submit">Sign in with GitHub</button>
24 </form>
25);
26}
🚀

Middleware for auth

For protecting multiple routes, combine Auth.js with middleware. Check the session in middleware and redirect unauthenticated users. This way you don't need auth checks in every individual page.

Watch and Learn