Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom verification function or disable verification #120

Closed
stongo opened this issue Nov 2, 2015 · 10 comments
Closed

Support custom verification function or disable verification #120

stongo opened this issue Nov 2, 2015 · 10 comments

Comments

@stongo
Copy link

stongo commented Nov 2, 2015

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

  1. Allow custom token verification function
  2. 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
@nelsonic
Copy link
Member

nelsonic commented Nov 2, 2015

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:

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!

@stongo
Copy link
Author

stongo commented Nov 2, 2015

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"

@nelsonic
Copy link
Member

nelsonic commented Nov 2, 2015

@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.

@stongo
Copy link
Author

stongo commented Nov 2, 2015

Right, but the drawback being the token gets verified twice (an extra time in key function

@nelsonic
Copy link
Member

nelsonic commented Nov 2, 2015

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.

@stongo
Copy link
Author

stongo commented Nov 2, 2015

Marking as closed. Realized the validate function doesn't pass the token anyway so following your advice. Thanks for your help!

@stongo stongo closed this as completed Nov 2, 2015
@nelsonic
Copy link
Member

nelsonic commented Nov 2, 2015

@stongo are you sure? if the you need a more specific solution to your quest we are happy to help further... 👍

@stongo
Copy link
Author

stongo commented Nov 4, 2015

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 stongo reopened this Nov 4, 2015
@nelsonic
Copy link
Member

@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...

@nelsonic
Copy link
Member

@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...)

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

No branches or pull requests

2 participants