Hi, I am generating the JSON web Token using the library but it is always returning me the same token for the same user each time...
Here is how I am generating the token.
var token = jwt.sign(user._id.toHexString(),process.env.SECRET)
it is generating the same token each time so anyone can get access to the token one time then can access the user using the token so is their a way for us to generate unique different tokens each time...?
An HMAC signature will always be the same for a header + payload combination that is equal.
You are unfortunately passing a string as the payload which
1) isn't conform to JWT which says the payload must be a JSON object
2) robs you of timestamp claim based validation such as iat, exp, nbf
Change your payload to be an object, set an expiration, get jti and iat in the payload and your tokens will be different on every sign.
I would also suggest you use an asymmetric algorithm instead, that means not passing a secret but rather a private key to the sign method.
@panva Even when a json is used, the library still returns the same token. My work around is to attach a timestamp field to the json and update it with Date.now() just before signing it. That way the json is technically different from the last one.
@makville I just want to make sure we're using the same terms here.
The token will be "the same" with the same payload, yes, simply because HS256 is a deterministic symmetric algorithm.
However, providing a JS object input (not JSON, that's just a string), an iat claim will be added automatically, and only if you happen to fall into the same second, it'll be the same signed JWT. It's basics.
const jwt = require('jsonwebtoken')
const secret = Buffer.from('b67ec320131d728efe107bd179c106e3bd24e621aed03a9e8e2004d9b3c0f6a1', 'hex')
const payloadObject = {
foo: 'bar'
}
const payloadJSON = JSON.stringify(payloadObject)
console.log(typeof payloadObject, payloadObject)
console.log(typeof payloadJSON, payloadJSON)
console.log('sign object input')
const signedObject = jwt.sign(payloadObject, secret)
console.log(signedObject)
console.log('sign string input')
const signedString = jwt.sign(payloadJSON, secret)
console.log(signedString)
console.log('setting a timeout')
setTimeout(function () {
console.log('sign object input')
const signedObject2 = jwt.sign(payloadObject, secret)
console.log(signedObject2)
console.log('signedObject === signedObject2', signedObject === signedObject2)
console.log('sign string input')
const signedString2 = jwt.sign(payloadJSON, secret)
console.log(signedString2)
console.log('signedString === signedString2', signedString === signedString2)
}, 2000);
object { foo: 'bar' }
string {"foo":"bar"}
sign object input
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NzU4MzQ0ODN9.cjq85z1rt6elPmgmtyuN3V46u1MX0Y6P-UnnkczfBDI
sign string input
eyJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.f4oFFcaE1wPHiYRSmTCfHVeNJztPgndVoRP4zuWX2Qo
setting a timeout
sign object input
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NzU4MzQ0ODV9.57FFpUoTJWMi00OsfwzzJoRv_lL5P4agxaSec4focak
signedObject === signedObject2 false
sign string input
eyJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.f4oFFcaE1wPHiYRSmTCfHVeNJztPgndVoRP4zuWX2Qo
signedString === signedString2 true
Recently I've encountered the same problem.
I got payload from a refresh token and I didn't notice that "iat" property was added there. Thus, the next time I signed the object with an existing "iat" property, and jsonwebtoken didn't update it. So, I was getting absolutely equal tokens all the time.
Most helpful comment
@makville I just want to make sure we're using the same terms here.
The token will be "the same" with the same payload, yes, simply because HS256 is a deterministic symmetric algorithm.
However, providing a JS object input (not JSON, that's just a string), an
iatclaim will be added automatically, and only if you happen to fall into the same second, it'll be the same signed JWT. It's basics.