I'm trying to parse and validate a JWT token in node.js based on this sample (authored in .NET): https://github.com/liveservices/LiveSDK/blob/master/Samples/Asp.net/AuthenticationTokenSample/JsonWebToken.cs
Here is my node js javascript that validates the token:
var validateSignature = function(key, claims, envelope, signature) {
var hasher = crypto.createHash('sha256');
hasher.update(key + "JWTSig");
var key = hasher.digest('binary');
var hmac = crypto.createHmac('sha256', key);
hmac.update(envelope + '.' + claims);
var out = hmac.digest('base64');
console.log(out);
console.log(signature);
console.log(out === signature);
}
Now, the very weird thing is - it almost works. Here's the output of the three console.log statements:
pEwNPJ+LUHBdvNx631UzdyVhPFUOvFY8jG3x/cP81FE=
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
false
It seems suspicious to me that the hashes are both the same except for the +-/_=
Anybody spot my mistake? Something to do with my base64 encoding.
UPDATE
I played some more and there seems to be something funky going on with base64 encoding here. The following code in node js:
console.log(signature);
var b = new Buffer(signature, 'base64');
console.log(b.toString('base64'));
yields:
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
pEwNPJLUHBdvNx631UzdyVhPFUOvFY8jG3xcP81F
Which seems very odd, right?
To verify a JWT, the server generates the signature once again using the header and payload from the incoming JWT, and its secret key. If the newly generated signature matches the one on the JWT, then the JWT is considered valid.
Javascript. }); Step 11: JWT verify method is used for verify the token the take two arguments one is token string value, and second one is secret key for matching the token is valid or not. The validation method returns a decode object that we stored the token in.
Thanks to Timothy Meade for commenting and pushing me in the right direction.
Node's Buffer type generates standard Base64 with +, / and =
There is a URL safe base64 encoding as mentioned here: http://en.wikipedia.org/wiki/Base64
It replaces + with -, / with _ and = is optional. The token that is passed on the QueryString (d'uh) is a URL safe version. Hence the difference.
Code was fixed by a simple:
out = out.replace('+','-').replace('/','_').replace('=','');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With