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