πͺ 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 torole=adminto 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:
- You provide a secret key that only your server knows.
- 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).
- When a request comes back, the server recalculates the signature and compares it to the one sent with the cookie.
- 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-parserconst 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-parsermiddleware with a secret and use the{ signed: true }option when setting the cookie. - Read unsigned cookies from
req.cookiesand signed cookies fromreq.signedCookies.