5

Context: I'm looking at storage solutions for JWT tokens on a single page application.

  1. Storing the JWT in the local storage is unsafe and prone to XSS attacks.
  2. Storing the JWT in a secure / HTTP only cookie is safer, but prone to CSRF attacks.

I'm studying the following scenario:

Upon authentication, a refresh token is stored in an http only secure cookie. It can only be used to get an access token.

Upon authorisation, the backend responds with a JWT access token. The header and payload part of the JWT are inside the response body. The token signature is not sent and is set in an http only secure cookie (same-site strict if possible, but let's assume it's not the case). The header + payload is stored in memory.

The JWT contains the following claims

  • iat, nbf, exp (guessable IMO)
  • claims relative to the user identity and permissions (guessable if the user identity is known)
  • jti, containing a cryptographically secure random number (in my case generated with python secrets)

When making requests, the header + payload is sent via XHR/fetch by the SPA in an Authorisation header. The signature is sent along with the cookies. The backend concatenates both and verify the signature.

  1. Is this mechanism safe against CSRF attacks ? Does the jti claims makes the Authorisation token + signature cookie a valid CSRF mitigation technique ?
  2. Is this mechanism indeed safer against XSS attacks than storing the JWT inside the local storage ? (Could an attack using XSS also easily steal the signature, like with a TRACE exploit).

Note: I've read this question which is similar, but overly broad so I'm posting this to get a more precise answer.

HHK
  • 153
  • 4
  • 1
    I've deleted my answer based on your comment. I hadn't considered that. The part that an attacker can't reproduce is the signature. Therefore if the signature is in the cookie, and an attacker can guess the JWT header, then they may be able to manage a CSRF attack. Whether or not this is possible will depend on what is yin your JWT, so I can't say how much of a risk that is. I suppose if you stored a long random string in each JWT then you wouldn't have to worry, since you would effectively be baking in your CSRF token (although at least you wouldn't need separate CSRF checks server side) – Conor Mancone Aug 18 '20 at 19:20
  • Ok, I'm going to modify the question to make it more focused on CSRF, and precise the shape of the JWT. – HHK Aug 18 '20 at 19:59

1 Answers1

2

Is this mechanism safe against CSRF attacks?

This method of splitting a JWT and storing the signature in the cookie and the rest of the token in Browser Storage does not provide any additional protection against CSRF attacks than if the entire JWT was stored in Local or Session Storage. Yes, it will mitigate CSRF attacks, but you don't need to add the unnecessary overhead of splitting and concatenating JWTs on the server. Storing JWTs in Local Storage and accepting them only in Authorization headers is enough to protect your application from CSRF attacks.

Is this mechanism indeed safer against XSS attacks than storing the JWT inside the local storage? (Could an attack using XSS also easily steal the signature, like with a TRACE exploit)

If your focus is solely on an attacker being able to steal JWTs, this approach is safe unless, as you rightly mentioned, TRACE is enabled on the server.

However, this does not make your application safer from XSS attacks. For example, if I am able to execute arbitrary Javascript on your application, I can fetch the JWT header+payload from Local Storage and just send an XHR to a sensitive endpoint keeping withCredentials set to True. This endpoint might be designed changed the account email address, for example. That straightaway leads to an account takeover. No need to steal cookies or JWTs.

Summing up: This approach does provide some protection against session tokens by separating the signature from rest of the token. However, when it comes to XSS, stealing session tokens is not the only risk that you should be looking at.

Amey
  • 284
  • 1
  • 2
  • Thanks for the response. I realise that storing the JWT in the localStorage is perfectly safe regarding CSRF, but it seemed to me that it's a really bad idea. According to [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage): `A single Cross Site Scripting can be used to steal all the data in these objects, so again it's recommended not to store sensitive information in local storage.` – HHK Aug 19 '20 at 07:14
  • Sorry, I deleted that comment immediately after posting. Hit enter before completing my comment. Take a look at how frontend frameworks like AngularJS, ReactJS, NextJS work. They have to access session tokens. I would say the OWASP advice you have pointed to is obsolete in terms of these JS frameworks. I am reiterating the fact that your approach secures your cookies from exfiltration through XSS, but it does not secure your application against XSS attacks completely. – Amey Aug 19 '20 at 07:34
  • Yes I agree that in case of an XSS, you are pretty much screwed anyway. Additional measures against account takeover need to be incorporated into the mix, but that's a bit out of the scope of my question. Essentially what you are saying is that, yes an attacker cannot go away with the token, but can do whatever he could have done with it anyway, so it's not that useful right ? – HHK Aug 19 '20 at 07:40
  • Yes, that's right.. – Amey Aug 19 '20 at 07:54