Next.js authentication patterns masterclass

Mobile Developer
December 8, 2024
Updated on December 31, 2024
0 MIN READ
#mobile-dev#react-native#next.js#authentication

Next.js Authentication Patterns Masterclass

Introduction

Authentication is a critical aspect of modern web applications, ensuring that users can securely access their data while keeping unauthorized users out. Next.js, with its hybrid rendering capabilities (SSR, SSG, and CSR), offers multiple ways to implement authentication, each with its own trade-offs.

In this masterclass, we’ll explore the most effective authentication patterns for Next.js, covering:

  1. Session-based authentication with NextAuth.js
  2. Token-based authentication (JWT) with API routes
  3. Middleware-based authentication in Next.js 13+
  4. Third-party authentication providers (OAuth, Auth0, Firebase)

By the end, you'll have a clear understanding of how to implement secure, scalable authentication in your Next.js applications.


1. Session-Based Authentication with NextAuth.js

NextAuth.js is the go-to library for session-based authentication in Next.js. It simplifies OAuth integration, email/password logins, and database sessions while supporting JWT for stateless authentication.

Setting Up NextAuth.js

First, install the package:

npm install next-auth

Next, configure pages/api/auth/[...nextauth].js:

import NextAuth from "next-auth";  
import GitHubProvider from "next-auth/providers/github";  

export default NextAuth({  
  providers: [  
    GitHubProvider({  
      clientId: process.env.GITHUB_ID,  
      clientSecret: process.env.GITHUB_SECRET,  
    }),  
  ],  
  secret: process.env.NEXTAUTH_SECRET,  
});

Protecting Routes

Use the useSession hook to check authentication status in client components:

import { useSession, signIn, signOut } from "next-auth/react"; export default function Dashboard() { const { data: session } = useSession(); if (!session) { return ( <button onClick={() => signIn("github")}> Sign in with GitHub </button> ); } return ( <> <p>Welcome, {session.user.name}!</p> <button onClick={() => signOut()}>Sign out</button> </> ); }

For server-side pages, use getServerSession:

import { getServerSession } from "next-auth"; import { authOptions } from "./api/auth/[...nextauth]"; export async function getServerSideProps(context) { const session = await getServerSession(context.req, context.res, authOptions); if (!session) { return { redirect: { destination: "/login", permanent: false } }; } return { props: { session } }; }

2. Token-Based Authentication (JWT) with API Routes

For applications requiring stateless authentication (e.g., mobile clients), JWT (JSON Web Tokens) is a popular choice.

Generating and Validating JWTs

Install jsonwebtoken:

npm install jsonwebtoken

Create a login API route (pages/api/login.js):

import jwt from "jsonwebtoken"; export default function handler(req, res) { if (req.method !== "POST") return res.status(405).end(); const { username, password } = req.body; // Validate credentials (e.g., against a database) if (username !== "admin" || password !== "password") { return res.status(401).json({ error: "Invalid credentials" }); } const token = jwt.sign( { username }, process.env.JWT_SECRET, { expiresIn: "1h" } ); res.status(200).json({ token }); }

Securing API Routes

Use middleware to validate JWTs in protected routes:

import jwt from "jsonwebtoken"; export default function handler(req, res) { const token = req.headers.authorization?.split(" ")[1]; if (!token) return res.status(401).json({ error: "Unauthorized" }); try { const decoded = jwt.verify(token, process.env.JWT_SECRET); res.status(200).json({ data: "Protected data", user: decoded.username }); } catch (err) { res.status(401).json({ error: "Invalid token" }); } }

3. Middleware-Based Authentication in Next.js 13+

Next.js 13 introduced middleware for running logic before a request completes. This is ideal for authentication checks.

Creating Middleware

Add a middleware.js file in your project root:

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 }); if (!token) { return NextResponse.redirect(new URL("/login", req.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard/:path*"], };

This redirects unauthenticated users from /dashboard/* to /login.


4. Third-Party Authentication Providers

For applications that prefer not to manage credentials, third-party providers like Auth0 or Firebase offer robust solutions.

Example: Firebase Authentication

Install Firebase:

npm install firebase

Initialize Firebase in a utility file:

import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; const firebaseConfig = { apiKey: process.env.FIREBASE_API_KEY, authDomain: process.env.FIREBASE_AUTH_DOMAIN, projectId: process.env.FIREBASE_PROJECT_ID, }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app);

Use Firebase in a login component:

import { auth } from "@/lib/firebase"; import { signInWithEmailAndPassword } from "firebase/auth"; export default function Login() { const handleLogin = async () => { try { await signInWithEmailAndPassword(auth, "user@example.com", "password"); } catch (error) { console.error(error); } }; return <button onClick={handleLogin}>Sign in with Firebase</button>; }

Conclusion

Next.js provides multiple authentication strategies, each suited for different use cases:

  • NextAuth.js for session-based auth with minimal setup.
  • JWT for stateless, API-driven applications.
  • Middleware for edge-based authentication in Next.js 13+.
  • Third-party providers for managed authentication solutions.

Choose the pattern that aligns with your security requirements, scalability needs, and development workflow. By leveraging these techniques, you can build secure, performant authentication flows in Next.js with confidence.

For further reading, explore the Next.js Authentication Docs and NextAuth.js Documentation. Happy coding! 🚀

Share this article