Auth.js (NextAuth) Simplified for Developers
Let’s talk about authentication. Specifically, Auth.js, formerly known as NextAuth.js. It’s a fantastic library for adding authentication to your Next.js applications. But like anything powerful, it can seem a bit daunting at first. My goal here is to cut through the noise and give you a practical, no-nonsense guide to getting it set up without pulling your hair out.
Why Auth.js?
First off, why bother with Auth.js? Because building authentication from scratch is a pain. You’ve got session management, CSRF protection, credential hashing, OAuth integration, and a whole lot more to worry about. Auth.js handles most of that for you, letting you focus on your app’s core features. It’s flexible, supports numerous providers (Google, GitHub, email, credentials, etc.), and integrates seamlessly with Next.js. Plus, it’s actively maintained, which is always a good sign.
The Core Concepts
Auth.js revolves around a few key pieces:
- API Routes: The authentication logic lives here. Typically at
/pages/api/auth/[...nextauth].js(or the equivalent in the App Router). - Configuration: You define your providers, database adapter (if using one), callbacks, and other settings here.
- Session Management: How user sessions are maintained (JWT or database). It handles token generation, verification, and cookie management.
- Providers: The external services you connect to for authentication (e.g., Google, GitHub).
- Callbacks: Functions that run at different stages of the authentication flow, allowing you to customize behavior, like modifying user or session objects.
Getting Started: A Basic Setup
Let’s get a simple email/password (credentials) provider up and running. We’ll assume you’re using the Pages Router for this example, but the concepts are similar for the App Router.
First, install Auth.js:
npm install next-auth# oryarn add next-auth# orpnpm add next-authNext, create your API route file. In a Pages Router project, this would be pages/api/auth/[...nextauth].js.
import NextAuth from 'next-auth';import CredentialsProvider from 'next-auth/providers/credentials';
export default NextAuth({ providers: [ CredentialsProvider({ name: 'Credentials', credentials: { username: { label: 'Username', type: 'text', placeholder: 'Your username', }, password: { label: 'Password', type: 'password', }, }, async authorize(credentials, req) { // Add your user validation logic here. // For example, query your database. const users = [ { id: '1', name: 'johndoe', email: 'john.doe@example.com', password: 'hashedpassword123' }, ];
const user = users.find(u => u.name === credentials.username);
// In a real app, you'd compare hashed passwords. if (user && credentials.password === 'password') { // Replace 'password' with your actual password check logic // Any object returned will be saved in 'user' property of the JWT passed to the callbacks return { id: user.id, name: user.name, email: user.email }; }
// If you return null then an error will be reported to the client return null;
// You can also Reject this callback with an Error or a short message to return // throw new Error('Invalid credentials'); }, }), ], session: { strategy: 'jwt', }, pages: { signIn: '/auth/signin', },});Notice the authorize function. This is where you’ll put your logic to verify a user’s credentials. In a real application, you’d be checking against a database, ideally comparing a hashed password. For simplicity, I’ve used a hardcoded check.
Protecting Routes
Now you need a way to show protected content only to logged-in users. You can do this in your pages/components using the useSession hook.
First, set up the Session Provider in your _app.js (or layout.js for App Router):
import { SessionProvider } from 'next-auth/react';
function MyApp({ Component, pageProps: { session, ...pageProps } }) { return ( <SessionProvider session={session}> <Component {...pageProps} /> </SessionProvider> );}
export default MyApp;Then, in your protected page or component:
import { useSession, signIn, signOut } from 'next-auth/react';
export default function Dashboard() { const { data: session, status } = useSession();
if (status === 'loading') { return <p>Loading...</p>; }
if (session) { return ( <> <p>Welcome, {session.user.name}!</p> <button onClick={() => signOut()}>Sign out</button> </> ); }
return ( <> <p>You are not signed in.</p> <button onClick={() => signIn()}>Sign in</button> </> );}Keep It Simple, Stupid (KISS)
Auth.js is powerful. Don’t get lost in all the options immediately. Start with a single provider, get your basic sign-in and session management working, and then layer on more complexity as needed. Use the documentation, but always bring it back to your specific needs. You’ve got this.
Tags: Web Development, Next.js, Authentication, Auth.js, NextAuth