Node.js Secure Cookies over HTTPS
This article explains how Node.js applications ensure secure cookies
are transmitted exclusively over encrypted HTTPS connections. It covers
the mechanics of the HTTP Secure attribute, how to
configure popular Node.js middleware to enforce this behavior, and how
to properly handle reverse proxies in production environments.
Under the hood, Node.js enforces secure cookie transmission by
appending the Secure attribute to the
Set-Cookie HTTP response header. This attribute is an
instruction to the user’s web browser, telling it never to send the
cookie back to the server over an unencrypted HTTP connection. If an
attacker attempts to intercept network traffic, or if the user
accidentally navigates to an HTTP version of the site, the browser will
withhold the cookie, protecting it from interception.
In the Node.js ecosystem, this behavior is typically configured using
session and cookie-parsing middleware like express-session
or cookie-parser. When defining the cookie settings,
developers must explicitly set the secure property to
true.
Here is an example of how to enforce secure cookies in an Express application:
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
secret: 'your-secure-secret',
resave: false,
saveUninitialized: true,
cookie: {
secure: true, // Restricts the cookie to HTTPS connections only
httpOnly: true // Mitigates XSS attacks by hiding the cookie from client-side JS
}
}));When secure is set to true, compliant
browsers will block the cookie from being sent over standard
http:// requests. During local development, testing this
configuration over HTTP can cause cookies to fail to store. To resolve
this, developers must either run a local HTTPS server or rely on modern
browsers that treat localhost as a secure origin by
default.
In production environments, Node.js applications are commonly deployed behind a reverse proxy, such as Nginx, Cloudflare, or a cloud load balancer. These proxies typically terminate the SSL/TLS (HTTPS) connection and forward the request to the internal Node.js process over HTTP.
Under these conditions, Node.js will detect an HTTP connection and
refuse to send the cookie if secure is enabled. To fix
this, you must configure Node.js to trust the reverse proxy. In Express,
this is achieved by enabling the trust proxy setting:
app.set('trust proxy', 1); // Trust the first proxy in front of Node.jsBy enabling this setting, Node.js reads the
X-Forwarded-Proto header passed by the proxy. If the header
indicates the client connected via HTTPS, Node.js recognizes the
connection as secure and safely transmits the cookie with the
Secure flag.