Is It Safe to Store a Jwt in Localstorage with Reactjs

Is it safe to store a JWT in localStorage with ReactJS?

In most of the modern single page applications, we indeed have to store the token somewhere on the client side (most common use case - to keep the user logged in after a page refresh).

There are a total of 2 options available: Web Storage (session storage, local storage) and a client side cookie. Both options are widely used, but this doesn't mean they are very secure.

Tom Abbott summarizes well the JWT sessionStorage and localStorage security:

Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS, in a nutshell, is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts <script>alert('You are Hacked');</script> into a form to see if it is run by the browser and can be viewed by other users.

To prevent XSS, the common response is to escape and encode all untrusted data. React (mostly) does that for you! Here's a great discussion about how much XSS vulnerability protection is React responsible for.

But that doesn't cover all possible vulnerabilities! Another potential threat is the usage of JavaScript hosted on CDNs or outside infrastructure.

Here's Tom again:

Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.

What if only one of the scripts you use is compromised? Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.

Therefore, my conclusion is that as a storage mechanism, Web Storage does not enforce any secure standards during transfer. Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.

Where token should be kept in a front end (reactjs)

A JWT needs to be stored in a safe place inside the user's browser.

If you store it inside localStorage, it's accessible by any script
inside your page (which is as bad as it sounds as an XSS attack can
let an external attacker get access to the token).

Don't store it in local storage (or session storage). If any of the
3rd part scripts you include in your page gets compromised, it can
access all your users' tokens.

The JWT needs to be stored inside an HttpOnly cookie, a special kind
of cookie that's only sent in HTTP requests to the server, and it's
never accessible (both for reading or writing) from JavaScript running
in the browser.

from: https://logrocket.com/blog/jwt-authentication-best-practices/

So you will need to set the cookie in the server side for it to be safe.

You can find an already widely accepted answer to this question here: https://stackoverflow.com/a/44209185/11465265

React and storing jwt token in localstorage

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.



Related Topics



Leave a reply



Submit