HeoLab
ToolsBlogAboutContact
HeoLab

Free developer tools with AI enhancement. Built for developers who ship.

Tools

  • JSON Formatter
  • JWT Decoder
  • Base64 Encoder
  • Timestamp Converter
  • Regex Tester
  • All Tools →

Resources

  • Blog
  • What is JSON?
  • JWT Deep Dive
  • Base64 Explained

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 HeoLab. All rights reserved.

Tools work in your browser. Zero data retention.

HomeBlogImplementing JWT Authentication in Next.js
Table of Contents▾
  • Table of Contents
  • Project Setup
  • .env.local
  • Generating Tokens
  • Login API Route
  • Protecting Routes with Middleware
  • Logout
tutorials#jwt#nextjs#authentication

Implementing JWT Authentication in Next.js

A step-by-step guide to building JWT authentication in Next.js with App Router, middleware, and secure cookie storage.

Trong Ngo
February 22, 2026
2 min read

Table of Contents

  • Project Setup
  • Generating Tokens
  • Login API Route
  • Protecting Routes with Middleware
  • Logout

Project Setup

npm install jose

We use jose — a modern, edge-compatible JWT library that works in Next.js middleware.

# .env.local
JWT_SECRET=your-256-bit-random-secret

Generating Tokens

// lib/jwt.ts
import { SignJWT, jwtVerify } from "jose";

const secret = new TextEncoder().encode(process.env.JWT_SECRET!);

export async function signToken(payload: Record<string, unknown>) {
  return new SignJWT(payload)
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime("15m")
    .sign(secret);
}

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, secret);
  return payload;
}

Login API Route

// app/api/auth/login/route.ts
import { signToken } from "@/lib/jwt";
import { cookies } from "next/headers";

export async function POST(req: Request) {
  const { email, password } = await req.json();
  const user = await verifyCredentials(email, password);
  if (!user) return Response.json({ error: "Invalid credentials" }, { status: 401 });

  const token = await signToken({ sub: user.id, email: user.email });
  (await cookies()).set('token', token, { httpOnly: true, secure: true, maxAge: 900 });
  return Response.json({ success: true });
}

Protecting Routes with Middleware

// middleware.ts
import { NextRequest, NextResponse } from "next/server";
import { verifyToken } from "@/lib/jwt";

export async function middleware(req: NextRequest) {
  const token = req.cookies.get('token')?.value;
  if (!token) return NextResponse.redirect(new URL("/login", req.url));
  try {
    await verifyToken(token);
    return NextResponse.next();
  } catch {
    return NextResponse.redirect(new URL("/login", req.url));
  }
}

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

Logout

// app/api/auth/logout/route.ts
import { cookies } from "next/headers";
export async function POST() {
  (await cookies()).delete('token');
  return Response.json({ success: true });
}

Try These Tools

JWT Decoder & Inspector

Decode and inspect JSON Web Tokens. View header, payload, and verify structure instantly.

Related Articles

Regular Expressions 101: A Beginner's Complete Guide

2 min read

The JWT Refresh Token Pattern Explained

2 min read

JWT vs Session Tokens: When to Use Each

2 min read

Back to Blog

Table of Contents

  • Table of Contents
  • Project Setup
  • .env.local
  • Generating Tokens
  • Login API Route
  • Protecting Routes with Middleware
  • Logout

Related Articles

Regular Expressions 101: A Beginner's Complete Guide

2 min read

The JWT Refresh Token Pattern Explained

2 min read

JWT vs Session Tokens: When to Use Each

2 min read