Why does decode with HMAC need a secret?

87 views
Skip to first unread message

Kevin Sun

unread,
Mar 3, 2022, 1:29:33 AM3/3/22
to ruby-jwt
Could anyone explain why decoding needs a secret? I am under the impression that in order to authorize the jwt, all I need to do is take the base64 encoded header and payload, then encode it myself with my own secret key to see if it matches with what the supplied secret key was in the jwt. 

So I'm a bit unclear as to why I need to supply a secret if all .decode is going to do is just show me the payload. 

Thanks,
Kevin

Kevin Sun

unread,
Mar 3, 2022, 1:31:54 AM3/3/22
to ruby-jwt
For context, I am referring to this part in the README:

# The secret must be a string. A JWT::DecodeError will be raised if it isn't provided. 
hmac_secret = 'my$ecretK3y'
token = JWT.encode payload, hmac_secret, 'HS256' 

# eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pNIWIL34Jo13LViZAJACzK6Yf0qnvT_BuwOxiMCPE-Y
puts token 

decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' } 

# Array 
# [ 
# {"data"=>"test"}, 
# payload 
# {"alg"=>"HS256"} 
# header 
# ] 
puts decoded_token

d...@52degreesnorth.com

unread,
Mar 7, 2022, 3:30:17 AM3/7/22
to ruby-jwt
The decode method does not *just* decode the token. It also verifies the token's authenticity and correctness.

> I am under the impression that in order to authorize the jwt, all I need to do is take the base64 encoded header and payload, then encode it myself with my own secret key to see if it matches with what the supplied secret key was in the jwt. 

Verifying the correctness of a JWT requires a number of steps:
1. splitting the token into the header and payload
2. decoding the header to identify and confirm the algorithm and potentially the key or secret used
3. using the algorithm and the key or secret to verify the authenticity of the payload
4. verifying that the "standard" claims in the payload are valid
5. verifying that any additional, non-standard claims in the payload are valid (this is application-specific)

The JWT would only be authorized if the claims in the signed payload are valid as well as the signature being valid.

JWT.decode performs all of these steps other than the non-standard claim verification (step 5 which is application specific); your suggestion of "checking the payload matches the signature" might do step 3 in some cases, but fails to verify the claims or properly validate the header, leaving your verification process open to many security vulnerabilities. The returned result is either an exception (indicating that the token is "bad" e.g. it is invalid, has an incorrect signature, has invalid claims) or the decoded values that you can use to perform step 5 above as required.

A typical payload may look like:
{ "exp": 1646641489, "nbf": 1646641401, "role": "admin" }

In this example, exp and nbf are standard claims that the library will verify, which mean that the token will be deemed invalid (and an exception would be raised) if the token is used after the expiry (exp) time or before the not before (nbf) time, and the non-standard "role" claim would be for you as the application developer to process.
Reply all
Reply to author
Forward
0 new messages