Cookie Security Guide for HttpOnly, Secure, SameSite
Compromised sessions are costly. The right cookie attributes make session theft and cross‑site attacks much harder. This guide shows safe defaults and concrete examples.
What to set and why
- HttpOnly: hides cookies from being extractable with JavaScript
- Secure: sends cookies only over HTTPS
- SameSite: controls cross‑site sending behavior (CSRF defense)
Safe defaults
Session cookies:
Set-Cookie: sessionId=...; Path=/; HttpOnly; Secure; SameSite=Lax
Sensitive actions may prefer SameSite=Strict
. Cross‑site/third‑party flows typically need SameSite=None; Secure
(modern browsers require Secure
when None
is used). Only use None
if the flow truly needs cross‑site cookies.
Framework examples
Node/Express:
res.cookie('sessionId', token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
path: '/',
})
Next.js (Route Handlers):
import { cookies } from 'next/headers'
cookies().set('sessionId', token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
path: '/',
})
ASP.NET Core:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => {
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
});
Django:
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Lax'
Testing
- Browser DevTools → Application → Cookies: verify attributes
- Check
Set-Cookie
headers in responses - Exercise login, logout, and cross‑site flows
Browser nuances
- Safari handles some cross‑site navigation and redirect chains differently. Test login/return flows with
SameSite=Lax
, redirects, and multiple tabs/windows. - Mobile webviews can cache aggressively. Ensure logouts clear relevant cookies.
Common mistakes
- Missing
Secure
in production - Using
SameSite=None
withoutSecure
- Storing JWTs in
localStorage
instead of HttpOnly cookies
Advanced tips
- Keep cookie lifetime short and rotate sessions on privilege changes
- Bind sessions to device hints (IP ranges, User‑Agent) if risk warrants
- Pair with CSRF tokens on state‑changing POST requests
Conclusion
Set cookies with HttpOnly, Secure, and a sensible SameSite by default. Test user flows and third‑party integrations, especially authentication, so that the security changes doesn’t break functionality.
Keep tabs on regressions with ongoing security checks in the Barrion dashboard.