tezvyn:

JWT Storage: Cookies (CSRF Risk) vs. Local Storage (XSS Risk)

AI-drafted, machine-checkedSource: cheatsheetseries.owasp.orgadvanced

Storing JWTs means choosing your risk: Cross-Site Request Forgery (CSRF) with cookies, or Cross-Site Scripting (XSS) with local storage. While local storage is simpler, HttpOnly cookies are generally safer as they can't be read by client-side scripts.

WHY IT EXISTS Once a user authenticates, a server issues a JSON Web Token (JWT) that the client must present with future requests. The client application needs a place to store this token between requests. The two most common places in a web browser are local storage and cookies, and the choice between them is a critical security decision.

THE MENTAL MODEL Choosing where to store a JWT is a direct trade-off between two major web vulnerabilities. Storing the token in local storage makes you vulnerable to Cross-Site Scripting (XSS). Storing it in a cookie makes you vulnerable to Cross-Site Request Forgery (CSRF). Your decision rests on which vulnerability you are better prepared to mitigate.

HOW IT WORKS Local Storage: You use JavaScript to place the token in storage (localStorage.setItem('token', jwt)). For every API call, your code must retrieve the token and manually add it to an Authorization: Bearer header. The critical flaw is that any JavaScript running on your page, including malicious code injected via an XSS attack, can read the entire contents of local storage and steal the token.

Cookies: The server sets the token in a Set-Cookie header. The browser automatically stores it and sends it with every subsequent request to the same domain. By setting the HttpOnly flag on the cookie, you make it inaccessible to JavaScript, effectively neutralizing XSS-based token theft. However, because the browser sends cookies automatically, you must use CSRF mitigation, primarily the SameSite attribute (Strict or Lax).

WHEN TO USE IT Use cookies when you can. An HttpOnly, Secure, SameSite=Strict cookie is the most secure method for storing JWTs in a browser. It protects against XSS theft and most CSRF attacks, and the browser handles the storage and transmission for you. This is the recommended approach for most web applications.

WHEN NOT TO USE IT Avoid local storage for session tokens if possible. Use it only when cookies are not feasible, such as in architectures with separate API and web domains that create cross-origin complexities, or for non-sensitive data. If you must use local storage, you absolutely need a very strict Content Security Policy (CSP) to reduce the risk of XSS, but it's never a complete guarantee.

ONE CANONICAL EXAMPLE An attacker finds an XSS vulnerability in a third-party library on your site. If the JWT is in local storage, the attacker's script runs localStorage.getItem('token') and sends the token to their server, hijacking the user's session. If the JWT is in an HttpOnly cookie, the same attacker's script tries to run document.cookie but gets an empty string; the token is protected by the browser and remains secure from the script.

Read the original → cheatsheetseries.owasp.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.