1

I have implemented a backend as a REST API. To maintain the statelessness in REST, I intend to use JWT to verify that that a user has logged in or not. (A user is logged in if a valid token is present in headers. Not logged in if a token is not present.)
But even with expiration times are set, an attacker can access the REST api by simply copying the JWT from the web browser. What are the methods available to stop this without killing the statelessness?

  • 2
    Great question! Your understanding is good, and as far as I know, the whole security model of JWTs is that copying the JWT from the browser is not "simple". Or if the attacker can do that, then might as well just use your logged-in browser. – Mike Ounsworth Mar 18 at 4:55
  • 1
    That's the point!. Considere when if an attacker has just one minute to peek on to your browser. Then all what he/she has to do is find the token(most probably in a js script's memory OR in my case--in Redux) and take a photo of it. Attacker can easily have 15 minutes to access unauthorized data! @MikeOunsworth – Rumesh Madhusanka Mar 18 at 5:08
2

While theft of the access tokens is a concern for all kinds of tokens, a special concern for stateless ones is that they can be used even after the user has logged out. As the receiving API does not have a source of truth apart from the token itself, it accepts any token that has not expired or otherwise been "globally invalidated" (for instance by revoking the signing key). And there are some things you can do to protect against damage from the loss of tokens in this case:

  • Make the token short lived, so that it will expire before attackers can steal and use it. You can set the expiry time to (for instance) 60 seconds, and keep refreshing it as long as the user is logged in.
  • Store the token in the browser in a manner that makes it more difficult to steal. For instance, using the session store makes it much less likely that someone can get it from a "hot desk" computer later.
  • Consider narrowing the scope of the token, so that if someone actually manages to steal it, they can't do as much damage. For instance, the Authorization Server could limit the roles in the token to a few necessary for the job the user is currently doing. This is complex, and thus is more important in a complex environment though.

The latter item can be adapted to limit any damage from misuse through XSS vulnerabilities to. Though those generally ruin your whole day anyway.

| improve this answer | |
  • If we make the token short lived-let's say 60 seconds, the expire time is defined in the token itself. If network errors occur randomly when obtaining a refresh token, how to deal with the failures? Is there any way to introduce a grace period (which the browser can re-attempt to obtain a new token) or something like that? otherwise user will have to login again and again for every minute or two. – Rumesh Madhusanka Mar 18 at 5:22
  • 1
    If the network fails when the user is fetching a new token, the client should simply retry the fetch. In the calling method, you can also verify that the token has some time left before expiry (say 5 seconds), and fetch a new one immediately before calling the API. – Geir Emblemsvag Mar 18 at 5:30
  • 1
    You say this is a common concern for stateless tokens but this is in fact a concern for all auth tokens (API keys, session tokens, etc...) Mitigation strategies are more or less the same in all cases – Conor Mancone Mar 18 at 9:51
  • True. I interpreted the OP as inquiring about the token being used after logout, where a stateful system would realize that the use was fraudulent. – Geir Emblemsvag Mar 18 at 10:57
  • With your first bullet of 60s token + refresh, what's stopping an attacker from refreshing it? I guess you're arguing that 60s is too short for an attacker extract it and call a refresh API? – Mike Ounsworth Mar 18 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.