DEV Community

Cover image for Why Cookie is preferable compared to localStorage when it comes to authentication
Duc Le
Duc Le

Posted on


Why Cookie is preferable compared to localStorage when it comes to authentication


We know about JWT, or JSON Web Token, as an industry standard RFC 7519 method for representing claims securely between two parties. JWT is very common nowadays. But where should we store them in the front end?

In this article, I will break down 2 common places to store tokens. Cookies and LocalStorage


Local Storage

To use localStorage, just simply call use the localStorage object

localStorage.setItem("yourTokenName", yourToken)
localStorage.getItem("yourTokenName", yourToken)
Enter fullscreen mode Exit fullscreen mode


  • Very convenient, don’t need any backend, just pure JavaScript.
  • Big Data size, about 5mb.


  • Vulnerable to XSS attacks. An XSS attack happens when an attacker can can take the access token that you stored in your localStorage because they can run JavaScript on your website.


To set cookie , we can do:

document.cookie = "cookieName=value"
Enter fullscreen mode Exit fullscreen mode

or do this with http request:

Set-Cookie: <cookie-name>=<cookie-value>
Enter fullscreen mode Exit fullscreen mode


  • If you’re using httpOnly and secure cookies this means that your cookies cannot be accessed using JavaScript so even if an attacker can run JS on your site, they can't read your access token from the cookie.
  • Can set expiration date


  • Only 4kb of storage

Security concerns

XSS Attacks

Like I said above, local storage is vulnerable because it’s easily accessible using JavaScript and an attacker can retrieve your access token. However, while httpOnly cookies are not accessible using JavaScript, this doesn't mean that by using cookies you are safe from XSS attacks involving your access token.

If an attacker can run JavaScript in your application, they can just send an HTTP request to your server which will automatically include your cookies; It’s just less convenient for the attacker because they can’t read the content of the token although they might don’t have to.

CSRF Attacks

Cross-site request forgery (also known as CSRF) is a web security vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform.

However, this can be mitigated easily using sameSite flag in your cookie by including an anti-CSRF token.


Cookies still have some vulnerabilities but it’s preferable compared to localStorage whenever possible. Because:

Both localStorage and cookies are vulnerable to XSS attacks, but it's harder for the attacker to do the attack when you're using httpOnly cookies.
Cookies are vulnerable to CSRF attacks, but it can be mitigated using sameSite flag and anti-CSRF tokens.
You can still make it work, even if you need to use the Authorization: Bearer header or your JWT is larger than 4KB.

Top comments (20)

brense profile image
Rense Bakker

If an attacker want to hack your site, they dont really care if they have to spend 1 extra minute to look for cookies with their malicious code... I'm sure they do that by default. Its important to remember that obscurity !== security. The whole point of jwt was to help protect against csrf attacks. By introducing sane standards that the user can follow that prevents these attacks by default. If you deviate from the normal jwt workflow, you get into danger territory. If you're worried about the contents of your jwt being stolen you should either encrypt it, or preferably, ask yourself why you're putting sensitive data in something that gets sent to the client browser. A jwt itself is not sensitive if you follow the normal path. But if you put user passwords in there, thats obviously a problem and something you should never do. XSS should obviously be avoided by not allowing code injection... If your app is open to code injection, there's nothing else you can do...

mjvmroz profile image
Michael Mroz

If someone manages to inject a script into your page, it's guaranteed that they can take action on behalf of your end users for as long as it's there. But that's a significantly better outcome than handing them the ability to exfiltrate secrets which permit them to act as your users for as long as the security tokens they've harvested are valid.

With JWTs, that's their expiry. And unless your users are logging in every day/hour, that's probably a fair way out. Most JWT-based auth implementations have no associated server-side state; that's why protocols like OAuth define a split between refresh and access tokens.

So that could be something like 30 days of irrevocable access that an attacker receives per harvested token because they got a script to execute once. Whereas a secure, http-only cookie can only be leveraged as long as the script is able to execute on the page. Much better.

Yes, XSS vulnerabilities should be avoided. But in the event that a browser or library bug opens you up to a vulnerability, you want the blast radius to be as small as possible. There's a reason for the expression "security comes in layers".

googoo_noonoo profile image
Googoo Noonoo

Where is the standard JWT workflow, which protects against CSRF, defined?

brense profile image
Rense Bakker

JWT was made to stop secret sharing like session IDs or login credentials between client and server. The attackers can see the values in the jwt, but they cannot make changes to it, because they do not know the secret on the server.

Thread Thread
googoo_noonoo profile image
Googoo Noonoo

But the author isn’t talking about the contents of a JWT being stolen, right? If you have access to the JWT from a CSRF injection, you can perform the malicious actions that the JWT authorises you to do. The author is saying you should use cookies so that the JavaScript interpreter cannot access any authentication data. I don’t think they’re concerned with the specific contents of the JWT.

Thread Thread
brense profile image
Rense Bakker

A CSRF attack is a trust problem on the server-side. The user is tricked into submitting a request they do not intend to make and the server accepts it because the session ID, for example, is trusted and linked to a particular user. CSRF attacks are naive. They dont know anything about the user, not even the session ID, but the attacker knows that a certain request will be accepted by the server (due to trust) aslong as a user previously logged in. A JWT always has to be sent together with the request by the user and the server needs to validate that JWT to confirm it has not been tampered with. In this case the server only trusts the secret that the JWT was encrypted with, not the JWT itself and that secret never leaves the server, effectively preventing CSRF. JWT is still vulnerable to XSS attacks, because in that case the attacker can access anything in the browser of the victim including the valid JWT and they can attach that to their malicious request. The only way to protect against XSS is to prevent it. Make sure no code can be injected by users.

rezarahmati profile image
Reza Rahmati

Storing data in localstorage has another issue, if you are using public computer and you close the browser still your data is there, so it would have been better to compare sessionStorage with cookies

primo profile image

Session storage is only accessible for one browser tab, so it's not even close to any of both. Besides, using public computer with normal browser (not incognito for example) window is dangerous!

szalonna profile image

Every time we argue about how to use the JWT token, we get to the point when we agree that we should only use JWT inside of the backend architecture and use standard session management between the client and backend. In this case we have the possibility to control the client as we can revoke a session any time, and still have the performance benefits of signed tokens as we use them only in secure environment. And on the API layer we can have a mapping which creates a short living access token only for authorize a request in between the services. In client perspective it is the same as we pass down a token as the client only attaches the token/session ID to every request.
And yes, you can blocklist any token any time but in this case what is the benefit of using token as you need to check the blocklist every time?

talr98 profile image

None are secured. Even if you backend is on the same domain of the server serving the frontend, I could use do actions on your behalf, without getting your token stored in the cookie:

// highlight-start
const userPickedImageUrl =
  '!jpg" onerror="fetch("https://localhost:3000/buy-product?prodid=abc", { credentials: "include", method: "POST" })'
// highlight-end

const contentWithUserInput = `
  <img src="${userPickedImageUrl}">

outputElement.innerHTML = contentWithUserInput
Enter fullscreen mode Exit fullscreen mode

Read more here:

pilcrowonpaper profile image

The benefits of using cookies rather than localsotrage are:

  1. Allows you do auth checks on server render
  2. Tokens can't be stolen - this doesn't mean the attacker can't do actions on behalf of the user, but the attack window is limited to the session since they store the stolen token.

To prevent CSRF, you can also check for the origin header, though as with same-site, it only works on modern browsers.

t0nyba11 profile image
Tony B

Nice article, but the last sentence didn't make sense to me...

Using the Authorization header means the token is then more accessible to XSS attacks, so I am not sure what "you can still make it work" means without giving up on the premise of your article (using httpOnly cookies)?

Also, I wasn't sure what you were suggesting for JWT's larger than 4KB in that last sentence either?

leduc1901 profile image
Duc Le

Sorry for bad wording from me.
What I tried to say is: Cookie is more preferable compared to localStorage.
Because cookies can do most of localStorage functionalities in somewhat better ways.
This article is a port from my medium page, so this is sort of a formatting mistake, you can check out my original post here:

jared201 profile image
Jared Odulio

i only keep flags to the localStorage e.g. subscribed, logged_in and remove these items (not set to false or anything!) when user closes the browser or become inactive. the better we don't share security practices, the worst the hacker can't assume to follow anything.

Sloan, the sloth mascot
Comment deleted
archnemesys profile image
Gonen R • Edited

If you don't protect the cookie against csrf and xss the cookie is still vulnerable and can be used to gain a fresh new access token, and with that token the attacker still has access to the rest of the APIs.

While it is an interesting approach, it does not free you from protecting the refresh token (the cookie).

nikki_eke profile image
Nikki Eke

I learnt something new today, thanks for sharing.

moofoo profile image
Nathan Cook

If you’re putting other sensitive data in a cookie that goes beyond the scope of how JWT are typically used, I would recommend using something like Iron Session instead.

marcroig profile image

Nice article, thank you!

fruntend profile image

Сongratulations 🥳! Your article hit the top posts for the week -
Keep it up 👍

Why You Need to Study Javascript Fundamentals

The harsh reality for JS Developers: If you don't study the fundamentals, you'll be just another “Coder”. Top learnings on how to get to the mid/senior level faster as a JavaScript developer by Dragos Nedelcu.