Validating a JWT in node.js
-
28-10-2019 - |
سؤال
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?
المحلول
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('=','');
نصائح أخرى
I wrote this library a while ago, I guess you can use some of the code. It is supposed to run in both node.js and in a modern browser.