DEV Community

Cover image for Next.js Authentication with JWT: Complete Guide for Secure Login in 2026
Synfinity Dynamics Pvt Ltd
Synfinity Dynamics Pvt Ltd

Posted on

Next.js Authentication with JWT: Complete Guide for Secure Login in 2026

Authentication is one of the most important parts of any modern web application. Whether you're building a SaaS platform, e-commerce store, admin dashboard, or AI-powered application, you need a secure way to identify users and protect sensitive routes.

In this guide, we'll build JWT Authentication in Next.js using the App Router, Route Handlers, Middleware, and HTTP-only cookies.

By the end of this tutorial, you'll understand:

  • What JWT authentication is
  • How JWT authentication works in Next.js
  • How to generate and verify JWT tokens
  • How to store tokens securely
  • How to protect routes using middleware
  • Security best practices for production applications

What Is JWT Authentication?

JWT (JSON Web Token) is a compact and secure method for transmitting user information between the client and server.

A JWT consists of three parts:

HEADER.PAYLOAD.SIGNATURE
Enter fullscreen mode Exit fullscreen mode

Example:

eyJhbGciOiJIUzI1NiIs...
Enter fullscreen mode Exit fullscreen mode

The token contains user information such as:

{
  "userId": "123",
  "email": "john@example.com",
  "role": "admin"
}
Enter fullscreen mode Exit fullscreen mode

The server signs the token using a secret key. Any tampering invalidates the token.

Why Use JWT Authentication?

JWT authentication offers several advantages:

  • Stateless authentication
  • Fast token verification
  • Easy scalability
  • Works well with APIs
  • Ideal for microservices
  • Widely supported across frameworks

JWT is commonly used in:

  • Next.js applications
  • React applications
  • Mobile apps
  • SaaS platforms
  • REST APIs
  • AI applications

JWT Authentication Flow

A typical JWT authentication flow looks like this:

  1. User enters email and password
  2. Server validates credentials
  3. Server generates JWT token
  4. Token is stored in an HTTP-only cookie
  5. User accesses protected routes
  6. Middleware verifies token
  7. Access is granted or denied

Project Setup

Create a new Next.js application:

npx create-next-app@latest jwt-auth-demo
cd jwt-auth-demo
Enter fullscreen mode Exit fullscreen mode

Install dependencies:

npm install jsonwebtoken bcryptjs
Enter fullscreen mode Exit fullscreen mode

Create Environment Variables

Create a .env.local file:

JWT_SECRET=super_secret_key_here
Enter fullscreen mode Exit fullscreen mode

Use a long and random secret in production.

Create Login API Route

Create:

app/api/auth/login/route.ts
Enter fullscreen mode Exit fullscreen mode
import { NextResponse } from "next/server";
import jwt from "jsonwebtoken";

export async function POST(request: Request) {
  const { email, password } = await request.json();

  if (
    email !== "admin@example.com" ||
    password !== "password123"
  ) {
    return NextResponse.json(
      { message: "Invalid credentials" },
      { status: 401 }
    );
  }

  const token = jwt.sign(
    {
      email,
      role: "admin"
    },
    process.env.JWT_SECRET!,
    {
      expiresIn: "1d"
    }
  );

  const response = NextResponse.json({
    success: true
  });

  response.cookies.set("token", token, {
    httpOnly: true,
    secure: true,
    sameSite: "strict",
    path: "/"
  });

  return response;
}
Enter fullscreen mode Exit fullscreen mode

This route:

  • Validates credentials
  • Generates a JWT token
  • Stores it in an HTTP-only cookie

Create JWT Verification Utility

Create:

lib/auth.ts
Enter fullscreen mode Exit fullscreen mode
import jwt from "jsonwebtoken";

export function verifyToken(token: string) {
  try {
    return jwt.verify(
      token,
      process.env.JWT_SECRET!
    );
  } catch {
    return null;
  }
}
Enter fullscreen mode Exit fullscreen mode

This helper will be used throughout the application.

Protect Routes Using Middleware

Create:

middleware.ts
Enter fullscreen mode Exit fullscreen mode
import { NextRequest, NextResponse } from "next/server";
import jwt from "jsonwebtoken";

export function middleware(req: NextRequest) {
  const token = req.cookies.get("token")?.value;

  if (!token) {
    return NextResponse.redirect(
      new URL("/login", req.url)
    );
  }

  try {
    jwt.verify(
      token,
      process.env.JWT_SECRET!
    );

    return NextResponse.next();
  } catch {
    return NextResponse.redirect(
      new URL("/login", req.url)
    );
  }
}

export const config = {
  matcher: ["/dashboard/:path*"]
};
Enter fullscreen mode Exit fullscreen mode

Now every route under:

/dashboard
Enter fullscreen mode Exit fullscreen mode

requires authentication.

Access User Data on the Server

Inside a protected page:

import { cookies } from "next/headers";
import jwt from "jsonwebtoken";

export default async function Dashboard() {
  const cookieStore = await cookies();

  const token =
    cookieStore.get("token")?.value;

  const user = jwt.verify(
    token!,
    process.env.JWT_SECRET!
  );

  return (
    <div>
      Welcome Back
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The server can safely verify the token before rendering.

Create Logout API Route

Create:

app/api/auth/logout/route.ts
Enter fullscreen mode Exit fullscreen mode
import { NextResponse } from "next/server";

export async function POST() {
  const response = NextResponse.json({
    success: true
  });

  response.cookies.set("token", "", {
    expires: new Date(0),
    path: "/"
  });

  return response;
}
Enter fullscreen mode Exit fullscreen mode

This removes the authentication cookie.

Security Best Practices

Use HTTP-Only Cookies

Never store JWT tokens in:

localStorage
Enter fullscreen mode Exit fullscreen mode

or

sessionStorage
Enter fullscreen mode Exit fullscreen mode

HTTP-only cookies reduce XSS attack risks.

Use Secure Cookies

Always use:

secure: true
Enter fullscreen mode Exit fullscreen mode

in production environments.

Set Token Expiration

Avoid tokens that never expire.

Example:

expiresIn: "1d"
Enter fullscreen mode Exit fullscreen mode

or

expiresIn: "2h"
Enter fullscreen mode Exit fullscreen mode

Validate Every Protected Request

Never trust client-side authentication.

Always verify JWTs on the server.

Use Refresh Tokens

For large applications:

  • Short-lived access token
  • Long-lived refresh token

This improves overall security.

Common JWT Authentication Mistakes

Storing Tokens in Local Storage

This makes tokens vulnerable to XSS attacks.

Using Weak Secrets

Avoid:

JWT_SECRET=123456
Enter fullscreen mode Exit fullscreen mode

Use long, randomly generated secrets.

Missing Token Expiration

Expired tokens improve security.

Relying Only on Frontend Checks

Attackers can bypass frontend checks.

Always validate tokens on the backend.

JWT vs Session Authentication

Feature JWT Session
Stateless Yes No
Scalable Yes Limited
Server Storage No Yes
API Friendly Excellent Good
Microservices Excellent Moderate

JWT is often preferred for modern cloud-native applications.

Conclusion

JWT authentication remains one of the most popular approaches for securing Next.js applications. By combining JWT tokens, HTTP-only cookies, Route Handlers, and Middleware, you can build a secure authentication system that scales with your application.

The key to secure JWT authentication is not just generating tokens but storing them safely, validating them correctly, and following security best practices.

Whether you're building a SaaS product, admin dashboard, AI application, or enterprise platform, implementing JWT authentication correctly will provide a strong foundation for user security.

FAQs

Is JWT better than sessions?

JWT is generally better for APIs and distributed systems, while sessions are often simpler for traditional web applications.

Should JWT be stored in localStorage?

No. Use HTTP-only cookies whenever possible.

Can JWT authentication be used with Next.js App Router?

Yes. Next.js App Router works very well with JWT authentication using Route Handlers and Middleware.

How long should a JWT token last?

Most applications use expiration periods between 15 minutes and 24 hours depending on security requirements.

Is JWT secure?

Yes, when used with strong secrets, secure cookies, HTTPS, expiration times, and proper server-side validation.

Top comments (0)