Skip to Content
πŸŽ‰ Welcome to my notes πŸŽ‰
Express.jsπŸͺ Signed vs. Unsigned Cookies

πŸͺ Signed vs. Unsigned Cookies

Cookies are a common way to store small pieces of information on a user’s browser. However, standard cookies are inherently insecure because they are just plain text that the user can easily view and modify. Express, with the help of middleware, provides a way to β€œsign” cookies to prevent tampering.

πŸ”“ Unsigned Cookies (The Default)

A standard, unsigned cookie is a simple key-value pair.

  • The Problem: Since the cookie’s value is stored on the client’s machine, a malicious user can easily change it. For example, if you stored a user’s role in a cookie like role=guest, the user could change it to role=admin to try and gain unauthorized access.
  • Use Case: Best for non-sensitive data, like theme preferences (e.g., theme=dark) or language settings.

πŸ” Signed Cookies (The Secure Way)

A signed cookie contains its original value plus a unique cryptographic signature generated by the server. This signature allows the server to verify that the cookie’s value has not been changed by the client.

  • How it Works:

    1. You provide a secret key that only your server knows.
    2. When you set a signed cookie, the server uses the secret key to create a unique signature based on the cookie’s value (e.g., using HMAC).
    3. When a request comes back, the server recalculates the signature and compares it to the one sent with the cookie.
    4. If the signatures match, the cookie is valid. If they don’t, Express knows the cookie has been tampered with and will reject it.
  • Analogy: A signed cookie is like a document in a sealed envelope with a unique wax seal. Anyone can hold the envelope up to the light to read the document (the data is not encrypted), but if they break the seal to change the document, the recipient (the server) will immediately know it has been tampered with.

⚠️ Important: Signing is not encryption. It only guarantees data integrity (that the data hasn’t been changed), not confidentiality. Never store highly sensitive data like passwords in cookies, even if they are signed.

Implementation in Express

To work with signed cookies, you need the cookie-parser middleware. First, you must install the package. Then, you initialize the middleware in your application by passing it a secret string. This secret is used to generate the signatures. When setting the cookie, you pass the option { signed: true }. Express will then automatically populate signed cookies in the req.signedCookies object, while standard cookies remain in req.cookies.

npm install cookie-parser
cookie-example.js
const express = require("express"); const cookieParser = require("cookie-parser"); const app = express(); // 1. Initialize cookie-parser with a secret. // This secret should be stored securely, e.g., in an environment variable. app.use(cookieParser("your-super-secret-key")); // 2. A route to SET both types of cookies app.get("/set", (req, res) => { // Setting a regular, unsigned cookie res.cookie("unsignedCookie", "This is easy to change!"); // Setting a SIGNED cookie res.cookie("signedCookie", "This is hard to tamper with!", { signed: true }); res.send("Cookies have been set!"); }); // 3. A route to GET the cookies app.get("/get", (req, res) => { // Read unsigned cookies from req.cookies const unsigned = req.cookies.unsignedCookie; // Read SIGNED cookies from req.signedCookies const signed = req.signedCookies.signedCookie; // If a signed cookie was tampered with, its value in req.signedCookies will be `false`. res.json({ unsignedCookie: unsigned, signedCookie: signed, }); }); app.listen(3000, () => console.log("Server is running on port 3000"));

How to Test:

Visit http://localhost:3000/set

Open your browser’s developer tools, go to the β€œApplication” or β€œStorage” tab, and look at the cookies. You’ll see unsignedCookie and signedCookie.

Try to change the value of unsignedCookie.

Visit http://localhost:3000/get. You’ll see your changed value.

Now, try to change the value of signedCookie.

Visit http://localhost:3000/get again. You’ll see that signedCookie is now false because the signature no longer matches the value.


✨ Summary

  • Unsigned cookies are insecure and can be easily modified by the user.
  • Signed cookies have a cryptographic signature to prevent tampering and ensure data integrity.
  • Signing does not encrypt the data; it only verifies that the value has not been altered.
  • To use signed cookies in Express, initialize the cookie-parser middleware with a secret and use the { signed: true } option when setting the cookie.
  • Read unsigned cookies from req.cookies and signed cookies from req.signedCookies.
Last updated on