9 min
  • HTTP
  • Cookies
  • Sessions
  • Authentication

Cookies and sessions

HTTP is stateless. Each request is complete on its own and the server has no memory of the last one — which is what lets caches and proxies reason about a single request without tracking a conversation, and is also why the web needed a workaround for "remember who I am".

The workaround is a cookie: a value the server asks the browser to store and send back on every later request to that site.

http
HTTP/1.1 200 OKSet-Cookie: __Host-sid=8f2c...; Secure; HttpOnly; SameSite=Lax; Path=/ GET /account HTTP/1.1Cookie: __Host-sid=8f2c...
Loading the HTTP Explorer simulation…

The cookie is a pointer, not the data

That value is almost always a random identifier and nothing else. The real

session — who you are, what you may do, when you logged in — lives on the server, where it can be revoked.

That indirection is what makes logging out mean something. Put the user's identity into the cookie itself and you cannot take it back: the browser holds it, the server has no list of what it issued, and the only expiry is the one you signed into it.

Check yourself
Why does a session cookie usually hold a random id rather than the user's identity?

The attributes are the whole security story

AttributeWithholds the cookie fromAttack it addresses
SecureAny cleartext HTTP requestNetwork interception
HttpOnlydocument.cookie, i.e. all JavaScriptXSS reading the session
SameSite=LaxCross-site POSTs and subresourcesCSRF
__Host- prefixAny weaker configuration than host-only, Path=/, SecureSubdomain injection

SameSite deserves care, because what it does is narrower than it sounds: the cross-site request is still sent, and the server still receives and executes it. What is withheld is only the cookie — so the request arrives unauthenticated and is rejected on that basis. That is exactly enough to stop CSRF and not one thing more.

Predict what happens next
A malicious page auto-submits a POST to your bank's transfer endpoint. Your session cookie is SameSite=Lax. What does the bank's server see?

Key takeaways

  • HTTP is stateless by design; a session is state bolted on by asking the browser to repeat a value.
  • The cookie normally holds an opaque id, and the session itself lives server-side — which is what makes revocation possible.
  • Secure keeps a cookie off cleartext, HttpOnly keeps scripts away from it, SameSite decides whether other sites’ requests carry it.
  • A cross-site request is still sent and still executed. SameSite withholds only the credential, which is exactly enough to defeat CSRF.
  • The __Host- prefix forces Secure, host-only and Path=/, because the name is the only part of a cookie the server gets back.

Take it further