Is it safe to store a JWT in sessionStorage?

How bizarre! I asked basically the same question about a month ago.

In the end, we decided that using localstorage for the JWT token was ok, as long as we also did the following on the HTTP level:

  • Ensure the entire site was served over HTTPS
  • Ensure the use of HSTS
  • Ensure that, once live, only the actual redirect URL was included in the Auth0 rules, as well as our source code
    • We use the Angular CLI. It turns out that, despite the tree shaking provided by WebPack, unused variables still show up in the compiled source code, for example localhost:4200
    • Make sure that there are no localhost URl's actually on Auth0 (on the allowed redirect page, for your client). Make a seperate Auth0 account for testing
  • Add the X-Frame-Options header to every HTTP response, and set it to Deny
  • Set X-XSS-Protection to 1
  • Set X-Content-Type-Options to nosniff
  • Make sure Content-Security-Policy is restricted to your own domain name, and any CDN's you may be pulling scripts in from
  • Set Referrer-Policy to same-origin
  • Limit the JWT expiry on Auth0 to 1 hour

The above will give you an A/A+ on securityheaders.io, and will prevent the most common attacks (somebody embedding your website in an iframe, and extracting data from localstorage, for example).


Well it depends. If you have an XSS vulnerability within your application an attacker can extract and use the JWT from your local storage.

A method I've used and I think Auth0 indicate is to use the cookie as the JWT storage and use the flags HTTP Only and Secure this way if you have an XSS vulnerability the cookie cannot be read and is only transported in a secure manner. CSRF is less of a risk these days as all the modern frameworks include CSRF mitigation.

This would mean validation extracts the JWT from the cookie on the server side to validate. My personal view is to use a cookie as storage as CSRF is easier to find and mitigate when compared to XSS attacks which have a large attack surface.