Secure Cookies: HttpOnly, Secure, and SameSite Explained
Cookies carry the session identifiers and tokens that keep users logged in, which makes them a frequent target for attackers. Secure cookies are those configured with the right attributes, principally HttpOnly, Secure, and SameSite, so that stealing or abusing them becomes far harder. Setting these flags correctly is one of the highest-value, lowest-effort improvements you can make to a web application's session security.
How Cookies Are Set
A server sets a cookie with the Set-Cookie response header, and the browser returns it on subsequent requests to the matching site. The attributes appended to that header control when and how the cookie is sent:
Set-Cookie: session=8f2a...; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
Each attribute addresses a specific threat, and using them together provides layered protection for the session identifier.
The HttpOnly Attribute
The HttpOnly attribute prevents client-side scripts from reading the cookie through document.cookie. Its purpose is to limit the damage of cross-site scripting: even if an attacker injects JavaScript, they cannot directly exfiltrate an HttpOnly session cookie.
It is important to understand the boundary of this protection. HttpOnly does not prevent XSS or stop an attacker from making requests as the user through injected script; it only keeps the cookie value out of JavaScript's reach. Apply it to every cookie that the browser does not legitimately need to read.
The Secure Attribute
The Secure attribute tells the browser to send the cookie only over encrypted HTTPS connections. Without it, a cookie can be transmitted over plaintext HTTP, where a network attacker could capture it. Marking session cookies Secure ensures they are never exposed on an unencrypted channel. Combined with serving the whole site over HTTPS and using HSTS, this closes the gap where a session token could leak in transit. Note that Secure governs transmission only; it does not encrypt the cookie's contents, so sensitive values should remain opaque references rather than readable data.
The SameSite Attribute
The SameSite attribute controls whether a cookie is sent on cross-site requests, and it is the primary browser-level defense against cross-site request forgery. It has three values:
- Strict: the cookie is withheld from all cross-site requests, including top-level navigations from another site. This is the safest option but can log users out when they arrive via external links.
- Lax: the cookie is sent on top-level navigations using safe methods, such as clicking a link, but not on cross-site subrequests or form posts. This balances usability and protection and is a common default.
- None: the cookie is sent on all cross-site requests and must be paired with
Secure. Use it only when a cookie genuinely needs to work in a third-party context.
Even with SameSite, anti-CSRF tokens remain valuable as defense in depth, since browser behavior and edge cases vary.
Scope Attributes and Prefixes
Domain and Path
The Domain and Path attributes control which requests receive the cookie. Keep scope as narrow as the application allows; a cookie scoped to a broad parent domain is exposed to every subdomain, widening the attack surface. Omitting Domain restricts the cookie to the exact host that set it, which is usually safer.
Lifetime
Max-Age and Expires set how long a cookie persists. Session identifiers should be short-lived and rotated after privilege changes such as login, which limits the window in which a stolen cookie is useful. A cookie with no Max-Age or Expires is a session cookie that the browser discards when it closes, which suits many authentication scenarios; persistent cookies survive restarts and should be reserved for cases where a longer-lived token is genuinely required.
Cookie Name Prefixes
Two special prefixes let a cookie assert its own security requirements, which the browser enforces:
- **
__Secure-** requires the cookie to be set with theSecureattribute over HTTPS. - **
__Host-** additionally requires noDomainattribute and aPathof/, binding the cookie tightly to the single origin that set it. This helps prevent subdomains from overwriting sensitive cookies.
A Practical Configuration Checklist
- Set
HttpOnlyon every cookie the front-end does not need to read. - Set
Secureon all cookies and serve the site exclusively over HTTPS. - Choose
SameSite=LaxorStrictfor session cookies, reservingNonefor genuine cross-site needs. - Narrow
DomainandPath, and prefer the__Host-prefix for sensitive session cookies. - Keep lifetimes short and rotate identifiers after authentication.
- Continue to use anti-CSRF tokens alongside
SameSite.
These settings work best as part of a broader defense that includes output encoding, a strong Content Security Policy, and careful session management, as explored across K0G.
Key Takeaways
- Secure cookies use
HttpOnly,Secure, andSameSiteto protect session identifiers from theft and misuse. HttpOnlykeeps cookies out of JavaScript, limiting the impact of cross-site scripting but not preventing it.Secureensures cookies travel only over HTTPS, andSameSiteis the main browser defense against CSRF.- The
__Host-and__Secure-prefixes let cookies enforce their own scope and transport requirements. - Narrow cookie scope, short lifetimes, and complementary anti-CSRF tokens complete a strong configuration.