Why is the signature part of a jwt token always different, even when created with the same values?
Asked Answered
C

2

9

jsonwebtoken, v8.5.0
node v10.13.0
npm 6.4.1

If i create a token several times with:

jwt.sign({ user_email: user_email, user_id: user_id, username: username }, 'RESTFULAPIs')  

Question 01:

It seems the first 2 parts of the string are always the same (the base64 encoded header and payload values), but the third part (the signature) is different.

Why is the signature different when the original values are the same?

What I've Tried:

I have read the signature section at jwt.io/introduction:

To create the signature part you have to take:

  • the encoded header
  • the encoded payload
  • a secret
  • the algorithm specified in the header

and sign that.

So, as a guess:

Is the signature the result of encrypting the base64 encoded header and payload values using the HS256 algorithm and secret, which in this case is the string RESTFULAPIs, which produces a different result each time it is encrypted, whilst the decoded result is always the same?


Question 02:

The decoded value of the different tokens is always the same, except for an object property called iat. What does that property represent?

{
iat: 1561358034
user_id: "25423537fshsdgA"
user_email: "[email protected]"
username: "bob"
}

{
iat: 1561358156
user_id: "25423537fshsdgA"
user_email: "[email protected]"
username: "bob"
}

Actually, after researching this second question more, I came across this:

The "iat" (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a NumericDate value.

Source: https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6

Croom answered 24/6, 2019 at 8:34 Comment(5)
so you answered question 2 already, right? When the IAT changes, it means the payload changes and different payload leads to a different signature. Btw., the signature is not "result of encrypting the base64 encoded header and payload values". The signature is a hash over heaer and payload.Petersburg
Actually, your observation regarding the different IAT makes the whole question invalid, because we're not talking about "the same values" anymore, your input might be the same, but IAT, which is added automatically, makes it different each time.Petersburg
Interesting insight about the payload changing due to the automatically added iat, i hadn't thought of that, however i have just double checked - when generating multiple tokens with the same header and payload (excluding the iat property that i assume jwt adds automatically when using jwt.sign()), the first two parts of all the tokens are the same (the encoded header and payload), whereas the third part is different (the signature).Croom
what do you mean by "excluding the iat property"? You got a token without iat? Then please update your question above and show us two tokens with identical header and payload but different signature.Petersburg
Actually, I think you were right, on closer inspection the first two parts of all the tokens i was generating were different by 3 characters (in 188 characters)! So your answer that the payloads were different, due to the automatically assigned iat property, which was causing the signature to be different, seems to be correct.Croom
T
10

Per the docs:

Generated jwts will include an iat (issued at) claim by default unless noTimestamp is specified. If iat is inserted in the payload, it will be used instead of the real timestamp for calculating other things like exp given a timespan in options.expiresIn.

So, you could test generating multiple jwts in the same second (which would therefore have the same iat) and verify that the signature is the same. Or, use the noTimestamp option, which would eliminate the iat and therefore make the payloads identical. I don't think this is the recommended way to do it.

But in short, iat is "issued at" as you've answered yourself, and the payload (and therefore the signature) is going to change every second as the inserted iat changes, per the docs I've quoted for you.

Tribulation answered 24/6, 2019 at 9:57 Comment(4)
So, does the existence of the iat during the jwt generation allows us to have the different token validity period durations (e.g. a token which is valid just for an hour)?Practise
@YaroslavTrofimov - sort of, but that's really what the exp claim is for. The iat claim should be used to determine the age of the token, and exp for its validity (see also nbf) - the RFC is here: tools.ietf.org/html/rfc7519#page-9Tribulation
Got it. Thank you.Practise
Unfortunately not a straightforward answerRattray
I
0

If you want to have same signature as output every time, you can convert the object you passed in first argument to JSON first (like using JSON.stringify()) and pass that JSON as argument. Then the jwt.sign() method will return same signature every time as iat property is not created by default.

Passing a JavaScript object in jwt.sign() as first argument will return new signature every time. This is because the property iat is added by default in this case by javascript.

Intisar answered 21/7 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.