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 loading jwk from json #221

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

kleinmrk
Copy link
Contributor

@kleinmrk kleinmrk commented Apr 3, 2022

This MR enables loading keys from json to jwk objects. It also adds an interface to the verifier class which accepts such keys and uses them as appropriate, based on the kid and alg claims, during token verification.

So far only RSA and oct keys can be loaded from json to jwk

  • RSA keys
  • EC keys
  • oct keys (HMAC)

@kleinmrk
Copy link
Contributor Author

kleinmrk commented Apr 3, 2022

This is still just a draft, there is much to do regarding error handling (currently I just lazily throw std::runtime_error all over the place) but I would be happy to hear your feedback, whether this PR goes the right direction.

Copy link
Owner

@Thalhammer Thalhammer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a bunch of small nitpicks and one thing I really think we should change.
One of jwt-cpp's strengths has been that its trivial to add custom algorithms and this has indeed been used in academics to research new ones.
The jwks part doesn't take that into account at all. While I get that the set of algorithms currently allowed in jwks is fixed, it might be useful to provide a way to add custom ones for research or if someone needs support of future algorithms before we add it.

Apart from that I have no major complains. Obviously documentation is non existant yet, but thats fine for a draft, just something we should keep an eye on before finishing it.

EDIT: Macos and no base seems to fail, so we need to take the user provided base64 function into account.


return pkey;
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key should definitly have some additional introspection methods, is it an async key ? if so rsa ? or ecdsa, what size ?
I think you get the point.

@@ -905,6 +943,9 @@ namespace jwt {
} else
throw rsa_exception(error::rsa_error::no_key_provided);
}

rsa(std::shared_ptr<EVP_PKEY> pkey, const EVP_MD* (*md)(), std::string name)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rather than the EVP_PKEY algorithms should take the key structure above, in order to reduce typing for the user and providing a nicer interface.

using alg_name = std::string;
using alg_list = std::vector<alg_name>;
using algorithms = std::unordered_map<std::string, alg_list>;
static const algorithms supported_alg = {{"RSA", {"RS256", "RS384", "RS512", "PS256", "PS384", "PS512"}},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a problem. The entire point of the algorithm support we used to have is to easily allow user defined algorithms, either for researching new ones or adding support for custom ones. A global list of algorithms doesn't really work out for that.

return nullptr;
}

if (alg_name == "RS256") {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above with supported_alg.

ec = error::token_verification_error::wrong_algorithm;
return;
}
algs.at(algo)->verify(data, sig, ec);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is my own code, but since we are already at changing it, this would be better:

auto alg = algs.find(algo);
if(alg == algs.end()) {
      ec = error::token_verification_error::wrong_algorithm;
      return;
}
alg->second->verify(data, sig, ec);

Prevents the duplicate lookup.

std::string keyid = "";
if (key.has_key_id()) {
keyid = key.get_key_id();
typename keysets::const_iterator it = keys.find(keyid);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto is your friend

@kleinmrk
Copy link
Contributor Author

@Thalhammer

One of jwt-cpp's strengths has been that its trivial to add custom algorithms and this has indeed been used in academics to research new ones.
The jwks part doesn't take that into account at all. While I get that the set of algorithms currently allowed in jwks is fixed, it might be useful to provide a way to add custom ones for research or if someone needs support of future algorithms before we add it.

I looked into how to make it possible to extend JWKs by custom algorithm and I ended up exposing algo_base and algo structures so the users can register their own algorithms like this. I don't know whether this is acceptable but I am out of other ideas. If you don't like the approach then please stop me now :D

@kleinmrk kleinmrk force-pushed the support-loading-jwk-from-json branch from 6e36d68 to abbd94f Compare October 2, 2022 15:53
new algo<jwt::algorithm::rs256>(jwt::algorithm::rs256(key.get_pkey())));
} else if (alg_name == "RS384") {
return std::unique_ptr<algo<jwt::algorithm::rs384>>(
new algo<jwt::algorithm::rs384>(jwt::algorithm::rs384(key.get_pkey())));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use make_unique

* \param jwt Token to check
* \param ec error_code filled with details on error
*/
void verify(const decoded_jwt<json_traits>& jwt, std::error_code& ec) const {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of code moved so the diff is very confusing. It hard to tell what is new 🙊

@kleinmrk kleinmrk force-pushed the support-loading-jwk-from-json branch from abbd94f to 55b5b14 Compare October 2, 2022 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants