Support custom verification function or disable verification
stongo opened this issue · 10 comments
I'm in the process of implementing Dex
The reason for this request is because Dex uses and rotates through multiple keys to sign JWT tokens. Added to the complexity is the fact one has to generate the keys to verify tokens from an array of modulus/exponent pairs.
This leaves this module's current paradigm of providing one key to pass to jwt.verify() a blocker.
I wondered about the following solutions
- Allow custom token verification function
- Option to disable token verification and allow verification to happen in the validate function (with a major warning that decoded will not be verified)
I would be more than glad to provide a PR if you would agree on a way to tackle this in this module
Hi @stongo,
Thanks for getting in touch. If I understand you correctly, your use case is needing to sign JWTs with multiple keys.
We have support for dynamic keys see:
- Docs: https://github.com/dwyl/hapi-auth-jwt2#additional-notes-on-key-lookup-functions ?
- Example: https://github.com/dwyl/hapi-auth-jwt2/blob/master/test/dynamic-key-server.js#L8
- Tests: https://github.com/dwyl/hapi-auth-jwt2/blob/master/test/dynamic-key-test.js#L8
Which means you "just" have to create your own keyFunc
and pass it in when registering the plugin. see: https://github.com/dwyl/hapi-auth-jwt2/blob/master/test/dynamic-key-server.js#L66
Please let us know if you need help with implementing a key
function to suit your needs. thanks!
Thanks for the quick response @nelsonic
The use case is not quite correct. There are multiple keys that one must try in the jwt.verify(token, secretOrPublicKey, [options, callback])
function.
In other words, jwt.verify() may fail with the first key generated from the first item in the array returned by the Dex jwks_uri
So the use case is "try all keys, only one will verify the token correctly, others will not. If none verify, then consider the verification a failure"
@stongo right, in the scenario you are describing you can simply have a list (array or object) of keys and iterate through them until you are sure the verification failed.
e.g: keyFunc.js
var keys = [ 'key1', 'key2', 'key3', 'etc' ];
var key;
var i = keys.length;
while(i > 0) {
if( jwt.verify(token, keys[i]) ) {
key = keys[i];
break; // we found the key we need
}
else { // keep iterating
i--;
}
}
return key || false;
This code is not elegant, but I think it will do what you need.
Right, but the drawback being the token gets verified twice (an extra time in key function
Agreed. Its suboptimal...
The way I would solve this is by using an Object to store the list of keys:
var keys = {
"k1":"yourkeyhere",
"k2":"anotherkeyhere",
"k3": "etc.etc..."
}
then store the name of the key inside the JWT:
var token = JWT.sign({"keyname":"k1", "other":"other claims" }, keys['k2'] );
and instead of verifying the JWT inside the keyFunc
you would decode it and extract the keyname
:
var decoded = JWT.decode(token); // decoding does not require us to know the key's name
return decoded.keyname; // the key to be used to verify THIS token.
Then in your validateFunc
you can do:
var key = keyFunc();
var verified = JWT.verify(token, key);
You could dynamically lookup the keyname in any DB if you prefer not use an Object in your app.
Marking as closed. Realized the validate function doesn't pass the token anyway so following your advice. Thanks for your help!
@stongo are you sure? if the you need a more specific solution to your quest we are happy to help further... 👍
Re-opening this because I realize both the keys
function signature and validate
function signature both don't include the token
, only decoded
In the case of Dex, the token is immutable because it only provides the public key which cannot be used for resigning a modified token.
So it seems then it might be handy to provide the raw token in the keys
function, or else as originally suggested have an option to leave all token verification to the validate
function
@stongo do you have an idea of the desired format for a custom_verification
function?
I have the editor open now and could add it as part of the next release...
@stongo the latest release 5.3.0
has added support for custom verification by supplying a verifyFunc
which gives you complete control over the verify process.
It also means you can bypass verification completely if you wish.
to bypass JWT verification simply callback with null, true, decoded
e.g:
var customVerifyFunc = function (decoded, request, callback) {
return callback(null, true, decoded);
};
Let me us know if you need anything else. 👍
(Closing this issue as I think its resolved, but feel free to re-open if not...)