DEV Community

Cover image for Creating a Custom Authentication System in Next.js With JWT
HexShift
HexShift

Posted on

1 1 1

Creating a Custom Authentication System in Next.js With JWT

Creating a Custom Authentication System in Next.js With JWT

While frameworks like NextAuth.js provide plug-and-play authentication, building a custom JWT-based system in Next.js gives you full control over user sessions and security. In this guide, we’ll create a basic authentication flow using JSON Web Tokens (JWT), covering user login, protected routes, and token verification.

Step 1: Setup Your Project

Start with a Next.js project:

npx create-next-app jwt-auth-app
cd jwt-auth-app
npm install jsonwebtoken bcryptjs

Step 2: Mock Users and Login API

Create a simple login API route at /pages/api/login.js:

import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";

const users = [
  { id: 1, username: "admin", password: bcrypt.hashSync("password", 10) },
];

export default function handler(req, res) {
  const { username, password } = req.body;
  const user = users.find((u) => u.username === username);
  
  if (user && bcrypt.compareSync(password, user.password)) {
    const token = jwt.sign({ id: user.id, username: user.username }, "secret", {
      expiresIn: "1h",
    });
    res.status(200).json({ token });
  } else {
    res.status(401).json({ message: "Invalid credentials" });
  }
}

Step 3: Protect API Routes With Middleware

Create a helper function to verify JWTs:

// lib/auth.js
import jwt from "jsonwebtoken";

export function verifyToken(req) {
  const authHeader = req.headers.authorization;
  if (!authHeader) return null;

  const token = authHeader.split(" ")[1];
  try {
    return jwt.verify(token, "secret");
  } catch {
    return null;
  }
}

Now use it in a protected route:

// pages/api/protected.js
import { verifyToken } from "../../lib/auth";

export default function handler(req, res) {
  const user = verifyToken(req);
  if (!user) {
    return res.status(401).json({ message: "Unauthorized" });
  }

  res.status(200).json({ message: "Protected data", user });
}

Step 4: Frontend Integration

In your component or login form, send credentials and store the JWT:

const handleLogin = async () => {
  const res = await fetch("/api/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ username: "admin", password: "password" }),
  });

  const data = await res.json();
  if (res.ok) {
    localStorage.setItem("token", data.token);
  }
};

Step 5: Call Protected Routes

const fetchProtected = async () => {
  const token = localStorage.getItem("token");

  const res = await fetch("/api/protected", {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  const data = await res.json();
  console.log(data);
};

Security Tips

  • Store tokens securely (e.g., HTTP-only cookies for production).
  • Use environment variables for your JWT secret.
  • Implement refresh tokens for longer sessions.

Conclusion

By building your own authentication system in Next.js using JWTs, you gain control over session behavior and token structure. This approach is flexible and scalable for custom app needs. While this example is basic, it sets the foundation for a more secure and robust solution.

If this post helped you, consider supporting me: buymeacoffee.com/hexshift

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (0)

👋 Kindness is contagious

Dive into this informative piece, backed by our vibrant DEV Community

Whether you’re a novice or a pro, your perspective enriches our collective insight.

A simple “thank you” can lift someone’s spirits—share your gratitude in the comments!

On DEV, the power of shared knowledge paves a smoother path and tightens our community ties. Found value here? A quick thanks to the author makes a big impact.

Okay