You can't for sure say that cookies are preferred to localStorage. It really depends on how you implement your app, what framework you are using and what exactly you want to do. let me describe it more precisely.
Cookie with httpOnly:
Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript.
When you store your jwt token in cookie and set it via http request set-cookie
on browser, then the browser will send this credentials on each request. Of course you can secure it by applying httpOnly
and secure
flag for that cookie. So that no javascript will access it. But the problem is that you are opening the chance to CSRF
attacks.
When the token is stored in a cookie, the browser will automatically send it along with each request to the same domain and this is still vulnerable to CSRF attacks.
localStorage:
On the other hand, jwt tokens are sent in Authorization header in each request. So browser doesn't set it automatically in your requests. it should be set on each request via javascript on client-side.
So basically because the browser doesn't add automatically to each request, it's not vulnerable to CSRF by default.
But the problem comes when your client code is vulnerable to XSS
. In that case, because you store your credentials on localStorage, Then attacker will have full control over client side and can do anything. The difference in using cookies, is that the attacker doesn't know the exact value of cookie which is stored with httpOnly flag. But he could send requests with that http headers.
So in my opinion it depends on following situations:
you want to save jwt tokens in localStorage, be sure that you check all your inputs and validate them. Use a framework that is not vulnerable to XSS
(for sure no framework can claim that, but at least use one that doesn't have reported CVEs recently). Also always update your client-side codes. Implement all security concepts like csp
and ...
Also be aware of what CDN you are using and be careful of which library you are using.
you prefer to use cookie and set credentials via Cookie on browser. Then be careful to implement anti-csrf mitigation techniques. always use https
and set secure
flag. be careful attacks that exist on cookie like subdomain and man in the middle attacks.
Also Django uses two cool method for handling this situations (read more about it here)
- Double-Submit Cookie
- Synchronizer Token
final note: I don't think there is a general solution for this topic and anyone can suggest based on it's experiments and knowledge.
BY the way, I prefer localStorage to store credentials received from Rest APIs.
But I really be glad if anyone could correct me for a better solution.