What are the security differences between storing a JWT in localStorage vs an HttpOnly cookie?
localStorage
- Accessible via JavaScript — any XSS vulnerability can steal the token:
document.cookie— wait, actuallylocalStorage.getItem('token'). - Token theft = account takeover. Attacker can make authenticated API calls from anywhere.
- Not automatically sent to the server — must manually attach:
Authorization: Bearer <token>.
HttpOnly cookie
HttpOnlyflag prevents JavaScript from reading the cookie — XSS cannot steal it.Secureflag ensures it only travels over HTTPS.SameSite=Strict/Laxprevents CSRF — cookie not sent on cross-origin requests.- Automatically included by the browser on every same-origin request — no manual header attachment.
Set-Cookie: token=<jwt>; HttpOnly; Secure; SameSite=Strict; Path=/
Verdict: HttpOnly cookies are strictly more secure. The main downside is CSRF risk (mitigated by SameSite) and that the token is sent on every request (including non-API routes) — use a short Path to scope it.