Implementing Authentication in Next.js with NextAuth.js

Search for a command to run...

No comments yet. Be the first to comment.
Next.js offers powerful rendering methods, one of which is Incremental Static Regeneration (ISR). This technique combines the performance benefits of static generation with the flexibility of server-side updates. In this guide, we'll explore how ISR ...
If you’re building modern web applications, chances are you’ve needed a simple backend for tasks like storing form submissions, feedback requests, or lightweight data logs. Instead of spinning up a server or managing databases, what if you could just...

Real-time applications, such as chat apps, require instant data exchange between clients and servers. In this guide, we'll walk through integrating Socket.io with Next.js (App Router) to build a real-time chat application. 🚀 Why Use Socket.io with ...

Managing global state in a Next.js application can be tricky, but Redux Toolkit (RTK) makes it easier by reducing boilerplate and improving performance. In this guide, we’ll walk through integrating Redux Toolkit with Next.js to efficiently manage ap...

Firebase is a powerful backend-as-a-service platform that offers authentication, real-time databases, and hosting. Integrating Firebase with a Next.js application allows you to build scalable and serverless web applications with ease. Why Use Fireba...

Optimization in Next.js App

NextAuth.js is a popular authentication library for Next.js that simplifies the process of implementing user authentication. It provides a robust and customizable solution for handling different authentication methods, including credentials, OAuth providers, and more. This guide walks you through setting up a basic authentication system in a Next.js application using NextAuth.js.
First, install NextAuth.js and the necessary dependencies:
npm install next-auth @next-auth/prisma-adapter
If you plan to use a database, make sure you have an ORM like Prisma or an appropriate adapter installed.
NextAuth.js requires an API route to handle authentication requests. Create a new file src/pages/api/auth/[...nextauth].ts:
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
export default NextAuth({
providers: [
Providers.GitHub({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
// Add more providers as needed
],
callbacks: {
async session({ session, user }) {
session.user.id = user.id;
return session;
},
},
secret: process.env.NEXTAUTH_SECRET,
});
This configuration uses GitHub as an OAuth provider. Replace GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET with your GitHub app credentials. You can add other providers as needed.
Add the required environment variables in a .env.local file at the root of your project:
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_secret_key
Replace your_github_client_id, your_github_client_secret, and your_secret_key with appropriate values.
Instead of using getServerSession, we can use middleware to protect routes and handle redirections. Create a middleware file in src/middleware.ts:
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
export async function middleware(req) {
const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
const { pathname } = req.nextUrl;
// Allow access to public paths
if (pathname.startsWith('/api/auth') || pathname === '/signin') {
return NextResponse.next();
}
// Redirect if no token is found
if (!token) {
return NextResponse.redirect(new URL('/signin', req.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
'/protected/:path*', // Protect paths that start with /protected
],
};
This middleware checks for a valid session token and redirects unauthenticated users to the sign-in page.
To allow users to sign in and out, create a simple component using NextAuth.js hooks:
import { useSession, signIn, signOut } from 'next-auth/react';
export default function AuthButton() {
const { data: session } = useSession();
if (session) {
return (
<>
<p>Signed in as {session.user.email}</p>
<button onClick={() => signOut()}>Sign Out</button>
</>
);
}
return <button onClick={() => signIn()}>Sign In</button>;
}
You can customize the authentication flow by modifying the pages property in the NextAuth.js configuration:
export default NextAuth({
pages: {
signIn: '/auth/signin',
signOut: '/auth/signout',
error: '/auth/error',
verifyRequest: '/auth/verify-request',
newUser: '/auth/new-user',
},
});
Create the corresponding pages in the src/pages/auth directory to match the paths defined above.
Centralized Logic: Middleware handles authentication at the route level, simplifying server-side logic.
Performance: Only restricted pages trigger session validation.
Flexibility: Easily configure protected and public routes.
To dive deeper into NextAuth.js and related topics, explore the following resources:
NextAuth.js Documentation - Official documentation with detailed guides and examples.
Securing Next.js Applications - Learn more about authentication strategies in Next.js.
These links provide additional insights and examples to help you expand your knowledge and make the most of NextAuth.js in your projects.