-1

I have been dealing with JWT for an auth API for my stateless app and I am really liking how JWT works but since storing JWT in local storage makes it vulnerable to XSS attacks, it kind of disappoints me. Though, I think if your app gets attacked by XSS, JWT tokens might be the last thing you would care about. On the other hand if the attacker decides to be sneaky and specifically aims to steal users' JWTs without having you noticed, it would be the worst case. I know each one of you guys have opinions about security of JWT but I am not here to discuss what's worst and what's best so far.

Instead, I will be talking about the new idea to make the best out of JWT for auth purposes, so to speak. By the way, I am not entirely sure if someone ever thought about this idea but I haven't read anything similar so far. If you have, I am sorry for the title and tell me who to give credits. Without further ado, let us begin.

First, I want you to know that we will be using long expiry time (for example 24 hours) for our tokens and will remain stateless but the problem with this is if your JWT ever gets stolen, anyone can use it, right? So, to prevent this issue we need to make the JWT unavailable for anyone other than the authentic user. We can achieve this by getting the user's IP address (and also user ID or what else you need) on login and storing it within the JWT payload. Then, to validate if the JWT is in the safe hands, we will check if the IP in the JWT payload matches with the IP which makes the request. If match, we pull the user ID from JWT payload then load user data into our global auth state. So, even if you somehow get your JWT stolen, they can't use it with another IP and that makes your JWT IP-specific. Also if you want to implement a real logout feature, you can use Redis to remain stateless while being able to revoke JWTs.

In a nut shell

  • Login user with credentials
  • Get the IP which makes the request
  • Put the IP within the JWT payload (and also user ID or what else you need)
  • Return the JWT and store it in local storage

Auto login with JWT;

  • Check if JWT exists in local storage
  • If exists, check if the IP which makes the request matches with the IP that is in the JWT payload
  • If match, pull the user ID from JWT payload to load user data into the global auth state
  • Done!
Dharman
  • 30,962
  • 25
  • 85
  • 135

1 Answers1

0
  1. This has been discussed many times before.
  2. This would not prevent attacks when the attacker is on the same network (corporate, NAT).
  3. This would not work for users that change their IP addresses normally (mobile to wired, between wifi networks and so on).
  4. Using a database (any kind, eg. Redis) to store state for logout is not stateless.

It might still have its use if circumstances are right (ie. it may mitigate certain threats in your threat model, while it may not mitigate others), but it is by far not a generic solution to solve this issue.

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
  • Thanks for your comment! This explains a lot. I have seen lots of discussions about JWT, Cookie, local storage and so on... It seems no one found a great way to accomplish this. Some people say Cookies are more battle-hardened but not modern. Some other say JWT are not suitable for auth. – Altug Karabas Jun 21 '20 at 18:27
  • There is a way where you put JWT in cookie and this prevents CSRF and XSS attacks at the same time. I think this is the best approach so far. So, I wonder what would you suggest? – Altug Karabas Jun 21 '20 at 18:31
  • Putting jwt in a cookie will not prevent csrf by default. You can use the newish `samesite` cookie attribute, which helps, but older browsers do not support that. I think jwts are mostly unnecessary, a plain old session id in a httponly cookie is usually better and more secure. Jwts have their use in complex single sign-on scenarios and some other cases (especially when real statelessness is required), but they are vastly overused without an actual understanding of their risks. – Gabor Lengyel Jun 22 '20 at 10:38