Skip to content

Instantly share code, notes, and snippets.

@ziluvatar
Last active April 11, 2024 07:10
Show Gist options
  • Save ziluvatar/a3feb505c4c0ec37059054537b38fc48 to your computer and use it in GitHub Desktop.
Save ziluvatar/a3feb505c4c0ec37059054537b38fc48 to your computer and use it in GitHub Desktop.
Example of refreshing tokens with jwt
/**
* Example to refresh tokens using https://github.com/auth0/node-jsonwebtoken
* It was requested to be introduced at as part of the jsonwebtoken library,
* since we feel it does not add too much value but it will add code to mantain
* we won't include it.
*
* I create this gist just to help those who want to auto-refresh JWTs.
*/
const jwt = require('jsonwebtoken');
function TokenGenerator (secretOrPrivateKey, secretOrPublicKey, options) {
this.secretOrPrivateKey = secretOrPrivateKey;
this.secretOrPublicKey = secretOrPublicKey;
this.options = options; //algorithm + keyid + noTimestamp + expiresIn + notBefore
}
TokenGenerator.prototype.sign = function(payload, signOptions) {
const jwtSignOptions = Object.assign({}, signOptions, this.options);
return jwt.sign(payload, this.secretOrPrivateKey, jwtSignOptions);
}
// refreshOptions.verify = options you would use with verify function
// refreshOptions.jwtid = contains the id for the new token
TokenGenerator.prototype.refresh = function(token, refreshOptions) {
const payload = jwt.verify(token, this.secretOrPublicKey, refreshOptions.verify);
delete payload.iat;
delete payload.exp;
delete payload.nbf;
delete payload.jti; //We are generating a new token, if you are using jwtid during signing, pass it in refreshOptions
const jwtSignOptions = Object.assign({ }, this.options, { jwtid: refreshOptions.jwtid });
// The first signing converted all needed options into claims, they are already in the payload
return jwt.sign(payload, this.secretOrPrivateKey, jwtSignOptions);
}
module.exports = TokenGenerator;
/**
* Just few lines to test the behavior.
*/
const TokenGenerator = require('./token-generator');
const jwt = require('jsonwebtoken');
const tokenGenerator = new TokenGenerator('a', 'a', { algorithm: 'HS256', keyid: '1', noTimestamp: false, expiresIn: '2m', notBefore: '2s' })
token = tokenGenerator.sign({ myclaim: 'something' }, { audience: 'myaud', issuer: 'myissuer', jwtid: '1', subject: 'user' })
setTimeout(function () {
token2 = tokenGenerator.refresh(token, { verify: { audience: 'myaud', issuer: 'myissuer' }, jwtid: '2' })
console.log(jwt.decode(token, { complete: true }))
console.log(jwt.decode(token2, { complete: true }))
}, 3000)
@TriStarGod
Copy link

@5eraph I believe it does both. The only thing I was unsure of was if the private key signed a message, whether that was considered encrypted or not. At first I believed it was due to https://security.stackexchange.com/questions/9957/can-i-use-a-private-key-as-a-public-key-and-vice-versa but I've to come to the conclusion its not. Proper implementation with both signing and encryption involves both parties sharing their public key to sign / encrypt messages to each other.

@5eraph
Copy link

5eraph commented Oct 12, 2020

@TriStarGod Interesting. I never thought about the internals of RSA and was thinking about crypto in general. I do not know whether this would be possible with other algorithms as well. But anyway your initial message may confuse someone to use public/private incorrectly, so it may be worth to update that answer.

@Mihir018
Copy link

Mihir018 commented Sep 5, 2023

I am not able to extract out

delete payload.iat;
delete payload.exp;
delete payload.nbf;

It seems this values does not exist on payload, is there some other way I can delete the old token and generate new one, or can someone help me on what I am missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment