7

I want to bring a doubt about JWT tokens and CSRF from the Stormpath post that explain the advantages and disadvantages of storing the JWT either in localStorage or cookies.

[...] if you are reading values out of a cookie using JS, that means you can't set the Httponly flag on the cookie, so now any JS on your site can read it, thus making it the exact same security-level as storing something in localStorage.

I'm trying to understand why they recommend adding the xsrfToken to the JWT. Doesn't storing your JWT in the cookie and then extracting it out and placing the JWT in the HTTP header and authenticating the request based on the HTTP header accomplish the same thing as Angular's X-XSRF-TOKEN? No other domain could make requests on a user's behalf if you authenticate based on the JWT in the header, since other domains cannot extract the JWT from the cookie. I don't understand the purpose of the xsrfToken in the JWT - perhaps its just an additional layer of defense - meaning that attackers would have to have a compromised script on your site and CSRF a user at the time. So they'd have to hit you in both ways to be able to pull of an attack.

The post is linked in this answer where says:

The last thing is to ensure that you have CSRF protection on every HTTP request to ensure that external domains initiating requests to your site cannot function.

[...] Then, on every request into your server, ensure that your own JavaScript code reads the cookie value and sets this in a custom header, e.g. X-CSRF-Token and verify that value on every request in the server. External domain clients cannot set custom headers for requests to your domain unless the external client gets authorization via an HTTP Options request, so any attempt at a CSRF attack (e.g. in an IFrame, whatever) will fail for them.

Even if they could set custom headers, they couldn't access the cookie where the JWT token is stored because only JavaScript that runs on the same domain can read the cookie.

The only way they could is via XSS, but having an xsrfToken in the JWT is compromised too if exists XSS vulnerabilities because a malicious script running in the trusted client domain could access the JWT in the cookie and include a header in the request with the xsrfToken.

So the equation should be:

  • TLS + JWT stored in secure cookie + JWT in request header + No XSS vulnerabilities.

If the client and server are running in different domains, the server should send the JWT and the client should create the cookie with the JWT. I think that the equation is still valid for this situation.

UPDATE: MvdD agree with me:

As the browser does not automatically add the header to your request, it is not vulnerable to a CSRF attack

Community
  • 1
  • 1
gabrielgiussi
  • 9,245
  • 7
  • 41
  • 71

2 Answers2

9

I am the author of the Stormpath Blog Post. Storing XSRF token in the JWT isn't about that it is in the JWT, it is about that it is in a cookie. The cookie should be httpOnly, so you can not read it from Javascript.

Now, I think the point that caused a little confusion is where I talk about angular. Angular sets it's only XSRF cookie as well (which is not httpOnly) to put it into the header at request time (which can only be done by javascript on same domain). These are not the same cookie.

If you think about implementing XSRF support in your application, this has been done with storing server side state and the point of storing the XSRF. Storing it in the httpOnly cookie is about being stateless with XSRF. Here, you would validate the JWT signature, get the XSRF out of the claims, and compare it to the header.

The answer to your question is so that you do not need to store state on your server.

Tom Abbott
  • 481
  • 3
  • 5
  • thanks for the answer, you have written a nice post! Still I can't see why a XSRF token is needed. Maybe if you share a concrete case where storing a JWT in a non httpOnly cookie and sending it back to the server in a header (with TLS and no XSS vulnerabilities) the user could make a malicious request without notice. – gabrielgiussi Jan 27 '16 at 22:34
  • Just posted an answer. Please let me know your thoughts. – Chiedo Jun 20 '16 at 12:29
  • I'm a fellow JMU grad also Tom :) – Chiedo Jun 20 '16 at 19:46
  • The downside of an explicit XSRF in JWT is that it increases size. Why not use a hash of JWT as the XSRF token directly? After all, if the attacker can read https-only cookies, your XSRF token isn't adding much value. And you can verify that hash without server-side state and without additional cookie size. – Eamon Nerbonne Feb 03 '17 at 10:47
  • @Tom quick one, do you reckon we should use xsref cookie and validate if we are using jwt for authentication – Nexus23 Nov 09 '17 at 14:18
9

My understanding was this:

  • Store JWT is an HTTPonly cookie.
  • In that JWT, store a hashed version of an XSRF token.
  • Send the client the XSRF token when they sign in so they can store it in local storage
  • Later when the client sends requests, the JWT is automatically sent with each request via cookies and then you also send the XSRF token via a header or query variable and on the server side, re-hash to compare to what's in the JWT on the server

Your JWT is protected from being stolen in a XSS and you're protected from XSRF. XSS could still execute on your browser but could only do damage for that session in the browser. Ultimately, You couldn't stop someone from writing a really detailed script that just ran on your browser, so conventional safeties to protect from XSS are still needed by the web developer.

Chiedo
  • 7,288
  • 3
  • 26
  • 22
  • 1
    That is correct! I wrote an answer in response to the vulnerability surface area with this approach here: http://stackoverflow.com/questions/37770967/jwt-tokens-in-sessionstorage-vs-cookies/37817530#37817530 – Tom Abbott Jun 21 '16 at 14:26
  • Also, go dukes! :) – Tom Abbott Jun 21 '16 at 14:26
  • 2
    I am still confused about this. So, is this a safe technique or not? Also, I don't understand why would I need the csrf. Because if I am storing in the local sotrage then is visible. Can you point in a the direction of an example! – Gacci Nov 19 '17 at 06:10
  • So why not store the jwt in the local storage AND XSRF token in a HttpOnly Coockie? This way the validity of the jwt would only be given when server receives both together. – Reiner Feb 15 '18 at 23:08
  • 1
    @Gacci you just need to investigate what XSRF attacks and CSS attacks are - the localStorage protects against the former (which is an attack that can't see localStorage) and the http-only cookie protects against the latter (which is an attack that can't exploit said cookie). – Rob Grant Apr 15 '18 at 19:55