1

I just recently started using jwt in a react+express app and came across the issue of where to store the jwt token. It seems like the two major options are localStorage and cookies with both being venerable to various attacks (XSS and CRSF).

But i found that react is supposedly XSS safe (What does it mean when they say React is XSS protected?) so is it okay to use localStorage to store the jwt? If not whats the industry standard for this?

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
LTM
  • 527
  • 1
  • 9
  • 18
  • Both attacks you have mentioned are not related to `token` storage i guess. Since `http` is a `stateless` protocol, we need to identify each request with something. Earlier this was session cookies, now a days it is tokens. Not much of a difference. – Panther Jul 05 '20 at 18:23
  • @Panther It's not true, both xss and csrf are very much related to token storage, and they have a very different risk profiles. See below. – Gabor Lengyel Jul 05 '20 at 18:52

1 Answers1

6

Both cookies and localStorage can be acceptable options, and both are used by many apps. You need to be aware of their pros and cons and choose what fits your usecase the best.

Cookies

  • Can be set as httpOnly, so javascript will not have access. This makes it impossible to access the token in an XSS attack. Note that this does not mean the app is not vulnerable to XSS. This only means then even in case of a successful XSS attack, the token will not be accessible to the attacker.
  • It's necessary to explicitly protect your app against CSRF as auth info will be sent automatically with requests.
  • Can only be sent to their origin (not to say APIs on different domains).
  • The token could probably be replaced by a plain old session id in that cookie as your app is likely not really stateless anyway. It would reduce complexity and increase security.
  • Cannot be used for access token storage in complex single sign-on scenarios with the identity provider having its own origin, and the app talking to several backends on different domains. In this case short-lived access tokens are usually stored in localStorage, with a longer-lived refresh token being set for the identity provider domain in a httpOnly cookie.

localStorage

  • Can be accessed by javascript, which includes a successful xss attack.
  • If the token is sent as a request header, no further protection is usually necessary against CSRF (the app is inherently protected, because authentication info is not sent automatically).
  • Tokens can be sent to different origins. This is the main benefit, and the most important reason you would use localStorage, or JWTs in general. If you only want to send the token to your single app origin, you probably don't need JWTs at all, and definitely don't want to use localStorage.

React being "XSS safe"

It's not. It's probably harder for a developer to make it vulnerable, but any medium complexity React app will most likely have XSS vulnerabilities. React is in no way immune to different forms of XSS. As long as developers have a multitude of options to insert user input into the DOM, there will be XSS, because sometimes it's the easiest to solve problems that way to "make it work". Content-Security-Policy might help somewhat in modern browsers if feasible in your app. It's true though that React is pretty secure by default, meaning that usually it will just be ok. That's a fairly standard requirement of any modern framework now, and it does not mean XSS in React is not possible. It is.

Ultimately, a session id stored in a httpOnly cookie (with correctly implemented session management, eg. as provided by your language or framework) is the most secure in general, followed by a token in a httpOnly cookie, but it also depends on your threat model and the exact usecase.

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59