You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
Securing your Next.js application requires authentication (who is the user?) and authorisation (what can they do?). This lesson covers NextAuth.js (Auth.js) setup, providers, session management, protecting routes, middleware, and role-based access control.
NextAuth.js (now called Auth.js) is the most popular authentication library for Next.js:
| Feature | Description |
|---|---|
| Multiple providers | OAuth (Google, GitHub), credentials, email |
| Session management | JWT or database sessions |
| Built-in pages | Sign-in, sign-out, error pages |
| CSRF protection | Automatic |
| TypeScript support | Full type safety |
npm install next-auth
// src/lib/auth.ts
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";
import bcrypt from "bcryptjs";
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHub({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
}),
Credentials({
name: "credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
if (!credentials?.email || !credentials?.password) return null;
const user = await prisma.user.findUnique({
where: { email: credentials.email as string },
});
if (!user || !user.hashedPassword) return null;
const isValid = await bcrypt.compare(
credentials.password as string,
user.hashedPassword
);
return isValid ? user : null;
},
}),
],
session: { strategy: "jwt" },
pages: {
signIn: "/login",
error: "/login",
},
});
// src/app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;
http://localhost:3000/api/auth/callback/googlehttp://localhost:3000/api/auth/callback/github# .env.local
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret-key-here
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
import { auth } from "@/lib/auth";
export default async function DashboardPage() {
const session = await auth();
if (!session) {
return <p>Please sign in.</p>;
}
return (
<div>
<h1>Welcome, {session.user?.name}!</h1>
<p>Email: {session.user?.email}</p>
</div>
);
}
"use client";
import { useSession } from "next-auth/react";
export default function UserMenu() {
const { data: session, status } = useSession();
if (status === "loading") return <p>Loading...</p>;
if (!session) return <a href="/login">Sign In</a>;
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.