0

I'm trying to understand how to use JWTs and more specifically, how not to use them.

Lets say I have a service that lets a user log in with a user name and password and I generate a JWT in response.

Next, the client passes this JWT as part of a request to my API that is located in a separate service. This service can verify that the signature is correct, whiteout knowing the secret key that was used to sign it with. It can also extract the claims.

enter image description here

But what's stopping a malicious user from just generating a JWT using any random secret key for signing, and modifying the claims?

The JWT below is signed using the key "my_super_Secret_key", not the original key that was used by my Identity service. I also changed my username to admin. When my service receives this JWT, it will see that it has a verifiable signature and happily extract the claims.

enter image description here

Should all incoming requests have the JWT verified against the secret key that was used to generate it?

Q-bertsuit
  • 3,223
  • 6
  • 30
  • 55
  • _"This service can verify that the signature is correct, whiteout knowing the secret key that was used to sign it with"_ - how? – jonrsharpe Jan 10 '23 at 11:41
  • No, you can't verify a JWT with a wrong secret. The results on jwt.io are sometimes misleading if you don't use it in the right way. In my answer in the linked Q/A I show how to use jwt.io correctly. – jps Jan 10 '23 at 11:42
  • @jps It doesn't answerer my question really. If you go into jwt.io and change one letter of the signature, it says "invalid signature", even without providing the secret, so there must be some way to verify that the signature is correct without knowing what the secret it. – Q-bertsuit Jan 10 '23 at 13:48
  • @jps The point is, I can send you a JWT and you can verify that the signature is valid. You don't need the secret to do that. I could also send you a JWT with an invalid signature, which you could also verify without the secret – Q-bertsuit Jan 10 '23 at 13:51
  • 1
    As long as you don't provide a secret, the signature is always considered invalid and I can't verify it without the correct key/secret. My answer describes exactly how to use jwt.io and the mistakes that can lead to a falsely verified signature. Please read my answer again carefully. – jps Jan 10 '23 at 13:53
  • @jps I'm sorry, you are correct. It was the user interface that confused me, like you suggested. Appreciate the help! – Q-bertsuit Jan 10 '23 at 13:57
  • 1
    No problem. I know that the user interface of jwt.io is confusing and I've seen and answered/commented on many questions that arise from this confusion. That was the reason I wrote that answer. – jps Jan 10 '23 at 13:59

1 Answers1

2

Firstly, your service must always verify the signature in a JWT. This is to prevent exactly the attack you describe where an attacker creates their own token with any claims they want and sends it to your app.

If you use symmetric cryptography (HS256 in your token is one), you need the original secret to verify the signature. If you use asymmetric cryptography (e.g. RS256), then you need the public key to verify the token. A private key is used to create the signature.

juunas
  • 54,244
  • 13
  • 113
  • 149
  • Thank you. So that means that for symmetric encryption all my services must have access to the secret used to create the JWT in order to verify it – Q-bertsuit Jan 10 '23 at 13:53
  • Yes, or they would need to send the token for verification to a service that has it. – juunas Jan 10 '23 at 14:03
  • 2
    For more complex scenarios with several services that need to verify a token, you should consider an asymmetric signature algorithm and sign with the private key and let the services verify with the public key. – jps Jan 10 '23 at 14:03