3
votes

I am working through some architecture issues in my head related to JWT authentication security and I'm trying to figure out the following:

  1. How does JWT securely pass a secret between server and client?

  2. Take a look at the below excerpt from from https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/ ....................

CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.

For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:

'When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. You can make this CSRF protection stateless by including a xsrfToken JWT claim:'

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

  1. How does the client create and send a valid request including the xsrfToken claim unless it can first sign the JWT after including the claim? (This xsrfToken after all is what's supposed to keep EvilBob from forging a request right?)

More details regarding my current understanding of the JWT XSRF process can be found here http://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/.

2

2 Answers

2
votes
  1. I can explain how Stormpath does it, there are some other ways as well. Stormpath includes a 'kid' (key id) field in the JWT header, which is the identifier for the API Key ID / Secret pair. The JWT was signed with the Secret, and the ID is stored in key id field. When Stormpath validates the token, it can retrieve the secret. This works across servers and services but is never passed to the client. Using the client to glue separate services together with the secret is extremely insecure.

  2. The client SHOULD NOT generate the JWT, this needs to be done on the server. The server knows the XSRF token and can sign it in the JWT and put it in the cookie.

Hope this information helps!

1
votes

The article appears to call this the "synchronized token pattern", however the solution described better fits with the Double Submit Cookies method rather than the Synchronizer Token Pattern.

Double submit cookies involves sending the cookie value in a header or body as well as sending it with the browser cookies that are automatically sent. If you are not supporting CORS, then setting a token in a header is secure anyway, as is with any custom header value (e.g. X-Requested-With). This is because a custom header cannot be sent cross-domain in the first place, so verifying that it has transported from the client verifies that it is not from another domain already. As a defence in depth strategy, you can set it to a random value, as explained by this answer.

The random value doesn't need to come from the server, nor be signed. It just needs to be generated by a CSPRNG. If generated client-side, window.crypto should be used for this. All the server does is check that the header and cookie values match.

A third party domain cannot forge a request because even though the cookie value will be sent by the browser automatically from the victim's machine, the attacker cannot include the value in the header or the request body.

With the Synchronizer Token Pattern the CSRF token is generated server-side and stored against the session. This value has to be sent from each form submission and is verified server-side that it matches the stored token.