devnotes.

Implement JWT authentication in Express app

JWT (JSON Web Token) authentication issues a signed token at login and verifies that token on protected routes, so the server can trust who's making a request without storing session state.

Step 1: Install dependencies

npm init
npm install jsonwebtoken mongoose express

Step 2: Sign-up and login routes

const express = require("express");
const mongoose = require("mongoose");
const jwt = require("jsonwebtoken");
const User = require("./userModel");

const app = express();
app.use(express.json());

app.post("/signup", async (req, res, next) => {
    const { name, email, password } = req.body;
    const newUser = new User({ name, email, password });

    try {
        await newUser.save();
    } catch {
        return next(new Error("Could not create the account."));
    }

    const token = jwt.sign(
        { userId: newUser.id, email: newUser.email },
        "library-secret-key",
        { expiresIn: "1h" }
    );

    res.status(201).json({
        success: true,
        data: { userId: newUser.id, email: newUser.email, token },
    });
});

app.post("/login", async (req, res, next) => {
    const { email, password } = req.body;
    let existingUser;

    try {
        existingUser = await User.findOne({ email });
    } catch {
        return next(new Error("Something went wrong."));
    }

    if (!existingUser || existingUser.password !== password) {
        return next(new Error("Invalid email or password."));
    }

    const token = jwt.sign(
        { userId: existingUser.id, email: existingUser.email },
        "library-secret-key",
        { expiresIn: "1h" }
    );

    res.status(200).json({
        success: true,
        data: { userId: existingUser.id, email: existingUser.email, token },
    });
});

mongoose
    .connect("mongodb://localhost:27017/librarydb")
    .then(() => {
        app.listen(3600, () => console.log("Server listening on port 3600"));
    })
    .catch(() => console.log("Database connection failed"));

Step 3: Verify the token on a protected route

app.get("/my-loans", (req, res) => {
    const authHeader = req.headers.authorization;

    if (!authHeader) {
        return res.status(401).json({ success: false, message: "Token missing" });
    }

    const token = authHeader.split(" ")[1]; // "Bearer <token>"

    try {
        const decoded = jwt.verify(token, "library-secret-key");
        res.status(200).json({
            success: true,
            data: { userId: decoded.userId, email: decoded.email },
        });
    } catch {
        res.status(401).json({ success: false, message: "Invalid or expired token" });
    }
});

Why JWT

  • Stateless — the server doesn't need to store session data.
  • Scalable — works well across multiple server instances.
  • Portable — the same token can be verified by any service that knows the secret (or public key, for asymmetric signing).
Implement JWT authentication in Express app | DevNotes