Back to List

What is a Cookie β€” HTTP State Management

Learn why HTTP cookies are needed, how they work, and what their security attributes are with Express examples.

Intermediate
|
10min
|
Verified (2026-07)
cookieHTTP state managementSet-Cookiesessionauthentication
Progress0/55 (0%)

What are Cookies? β€” HTTP State Management

After completing this topic, you will be able to:

Understand why HTTP is a "stateless" protocol, explain how cookies solve this problem, and know how to set and read cookies in Express.


HTTP Has No Memory

The HTTP protocol is stateless. After processing a request, the server completely forgets the client.

text
Client: GET /page1 β†’ Server: "Here is the content of Page 1"
Client: GET /page2 β†’ Server: "Who are you? Nice to meet you. Here is the content of Page 2"

The server cannot tell if the browser that requested /page1 one second ago is the same user. Login, shopping carts, dark mode settingsβ€”any feature that "remembers previous requests" is impossible due to this stateless nature.

Cookies solve this problem. It's like the server saying to the client, "Store this information and show it to me the next time you come."


How Cookies Work

Cookies are exchanged through HTTP headers.

text
1. Server β†’ Client (response header)
   Set-Cookie: username=Hoon; Path=/

2. Client β†’ Server (next request's request header)
   Cookie: username=Hoon

Once set, the browser automatically includes the cookie in all requests to the same domain. The browser sends it without the server having to ask. This is the core mechanism of cookies.


Handling Cookies in Express

Setting Cookies

javascript
const express = require('express');
const app = express();

app.get('/login', (req, res) => {
  // Send the Set-Cookie header
  res.cookie('username', 'Hoon', {
    maxAge: 24 * 60 * 60 * 1000, // 1 day (milliseconds)
    httpOnly: true,
    secure: false,    // Only transmit over HTTPS (set to false during development)
    sameSite: 'lax'
  });
  res.json({ message: 'Logged in, cookie set' });
});

Reading Cookies

To read cookies, you need the cookie-parser middleware.

bash
npm install cookie-parser
javascript
const cookieParser = require('cookie-parser');
app.use(cookieParser());

app.get('/profile', (req, res) => {
  const username = req.cookies.username;
  if (!username) {
    return res.status(401).json({ error: 'Not logged in' });
  }
  res.json({ message: `Welcome back, ${username}` });
});

cookie-parser parses the Cookie header and creates a req.cookies object. Without this middleware, you would have to parse the header yourself.

Deleting Cookies

javascript
app.get('/logout', (req, res) => {
  res.clearCookie('username');
  res.json({ message: 'Logged out, cookie cleared' });
});

clearCookie immediately expires the cookie with the same name.


Cookie Attributes

AttributeDescriptionExample
maxAgeLifetime (in milliseconds). Cookie is automatically deleted after this time86400000 (1 day)
expiresExpiration date (Date object). Less commonly used than maxAgenew Date('2026-12-31')
httpOnlyCannot be accessed by JavaScript (key for XSS protection)true
secureOnly transmitted over HTTPS connectionstrue
sameSiteWhether to include the cookie in requests from other sites'strict', 'lax', 'none'
pathCookie is only transmitted for paths below this path'/'
domainDomain for which the cookie is valid'.example.com'

Of these attributes, httpOnly and secure are the most important for security.


Security β€” Keeping Cookies Safe

httpOnly

javascript
// Bad β€” Cookie can be accessed by JavaScript (XSS vulnerability)
res.cookie('token', 'abc123');

// Good β€” Cannot be accessed by JavaScript
res.cookie('token', 'abc123', { httpOnly: true });

Setting httpOnly: true prevents reading the cookie with document.cookie. Even if an XSS attacker injects a script, they cannot steal the cookie. This should always be set for authentication-related cookies.

secure

javascript
res.cookie('token', 'abc123', {
  httpOnly: true,
  secure: true  // Only transmit over HTTPS
});

The cookie is not transmitted over HTTP (unencrypted) connections. An attacker cannot intercept the cookie.

sameSite

javascript
res.cookie('token', 'abc123', {
  httpOnly: true,
  secure: true,
  sameSite: 'strict'  // Only transmit on requests from the same site
});
ValueBehavior
'strict'Cookie is included only in requests from the same site. Completely blocks CSRF. However, the user will be logged out if they navigate to the site from an external link.
'lax'Allows GET requests (link clicks) but blocks POST requests. A compromise between CSRF protection and usability. Recommended.
'none'Included in all requests. Requires secure: true. Only used for cross-site APIs.

Cookies vs. Local Storage

CookielocalStorage
Sent to serverAutomatically included in every requestNot sent
Size~4KB~5MB
ExpirationCan expire automaticallyOnly deleted manually
AccessCannot be accessed by JavaScript if httpOnly is setOnly accessible by JavaScript
Use caseAuthentication, sessions, server settingsUI state, cache, offline data

Use cookies for "information that the server needs to know," and localStorage for "information that only the browser needs to know."


Real-world pattern β€” Dark mode cookie

javascript
// Setting dark modeβ€”can be applied during server-side rendering
app.post('/settings/theme', (req, res) => {
  const { theme } = req.body; // 'dark' or 'light'
  res.cookie('theme', theme, {
    maxAge: 365 * 24 * 60 * 60 * 1000, // 1 year
    httpOnly: false,  // JavaScript access required to apply CSS
    sameSite: 'lax'
  });
  res.json({ theme });
});

app.get('/', (req, res) => {
  const theme = req.cookies.theme || 'light';
  res.render('index', { theme });
});

For settings that are not security-sensitive, such as dark mode, you can set httpOnly: false. However, you should never set httpOnly: false for authentication tokens.


Key Takeaways

ConceptSummary
HTTP StatelessThe server does not remember previous requests
CookieA small piece of data that the server asks the client to store
Set-CookieServer β†’ Client (response header)
CookieClient β†’ Server (request header, automatic)
httpOnlyPrevents JavaScript access (XSS protection)
secureOnly transmitted over HTTPS
sameSiteCSRF protection (lax recommended)

Cookies are one of the oldest state management mechanisms on the web, but they are still widely used. Sessions, authentication, user settingsβ€”all of these are based on cookies. If you forget to set the security attributes (httpOnly, secure, sameSite), you will be vulnerable to XSS and CSRF attacks, so always check these three when setting cookies.


Production Checklist

When setting authentication cookies, be sure to check these items:

javascript
res.cookie('session_token', token, {
  httpOnly: true,       // βœ“ XSS protection β€” Prevents JavaScript access
  secure: true,         // βœ“ HTTPS only β€” Prevents plain text transmission
  sameSite: 'lax',      // βœ“ CSRF protection β€” Blocks cross-site POST requests
  maxAge: 3600000,      // βœ“ Set expiration β€” Prevents persistent cookies
  path: '/'             // βœ“ Restrict path β€” Limit to necessary scope
});

If you miss any of these, it will create a security vulnerability. Be sure to check this checklist before deploying to production.

πŸ’¬ Questions & Comments

0 comments

You can post without signing in. Guest comments cannot be edited or deleted by their author.

0/2000

Loading...