How to Secure Your Node.js API with JWT and Cookies

Blog

Posted by Nuno Marques on 2 Mar 2025

How to Secure Your Node.js API with JWT and Cookies

Introduction

Securing your Node.js API is crucial to protecting user data and preventing unauthorized access. JSON Web Tokens (JWT) combined with Secure HttpOnly Cookies offer a robust authentication strategy. In this guide, we’ll explore how to implement JWT authentication using Secure Cookies and avoid common security pitfalls.

Estimated reading time: 7 minutes


Why JWT and Secure Cookies?

JWTs are widely used for authentication because they allow stateless authentication, reducing the need for session storage. However, storing JWTs in Local Storage is dangerous due to XSS vulnerabilities. Instead, Secure HttpOnly Cookies provide a safer alternative.

Stateless authentication using JWTs

HttpOnly Cookies prevent XSS attacks
Secure attribute ensures data transmission only over HTTPS
SameSite flag helps prevent CSRF attacks


Setting Up JWT Authentication in Node.js

1. Install Dependencies

Start by installing the necessary packages:

npm install express jsonwebtoken cookie-parser dotenv cors

2. Configure Environment Variables

Create a .env file to store your secret key:

JWT_SECRET=your_strong_secret_key
JWT_EXPIRATION=1h

3. Generate JWT Tokens

const jwt = require("jsonwebtoken");

const generateToken = (userId) => {
  return jwt.sign({ id: userId }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRATION,
  });
};

4. Set HttpOnly Secure Cookies on Login

const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser());

app.post("/login", (req, res) => {
  const token = generateToken(req.body.userId);
  res.cookie("authToken", token, {
    httpOnly: true,
    secure: true,
    sameSite: "Strict",
    maxAge: 3600000,
  });
  res.json({ message: "Login successful" });
});

5. Verify JWT Tokens in Middleware

const verifyToken = (req, res, next) => {
  const token = req.cookies.authToken;
  if (!token) return res.status(401).json({ message: "Unauthorized" });

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.status(403).json({ message: "Forbidden" });
    req.user = user;
    next();
  });
};

Key Security Considerations


Next Steps

  • Implement CSRF protection strategies.
  • Secure API endpoints with role-based authentication.
  • Explore OAuth2 for third-party authentication.

Related Articles