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

Keyfunc() method does not check the "use" value to enforce correct usage of JWKs #53

Closed
trevorlyman opened this issue Sep 29, 2022 · 1 comment
Labels
enhancement New feature or request

Comments

@trevorlyman
Copy link
Contributor

Keyfunc() only selects a JWK based upon the kid. The Json Web Signature (JWS) RFC (see appendix D point 2.) suggests that keys should be filtered based upon their "use" field when selecting a key to use for verification. This could become an issue when the key is appropriate for encryption, but not for verifying signatures (i.e. someone tried to sign a JWT with an encryption key).

This filtering could be enforced by the Keyfunc() method by checking the "alg" value of the JWT and enforcing the JWK "use" value to be for signature or encryption as appropriate.

I would be happy to submit a PR to do add this filtering functionality. One challenge I see is getting the context associated with the key (kty, alg, use, ect...). Right now it looks like we only hold onto the public key interface and not the metadata associated with the JWK (maybe I missed this?).

@MicahParks MicahParks added the enhancement New feature or request label Oct 1, 2022
@MicahParks
Copy link
Owner

Thank you for opening this issue.

The "use" parameter in a JWK is also defined in RFC 7517 section 4.2: https://www.rfc-editor.org/rfc/rfc7517#section-4.2. Regarding that parameter, this package is only interested in JWK that have the value "sig". It seems to me this issue is suggesting that if the "use" parameter is given in a JWK and the value is not "sig", then the key should be ignored. Since this JWK parameter is optional, I think it could be classified as an "enhancement".

This sounds like a good issue to me. I'd be happy to implement it, but if you'd like to contribute you are welcome to be the one to implement this. Let me know which you would like.

If you are curious, this is how I would do it. (Spoiler alert)

  1. Add a new field to the unexported data type, jsonWebKey, for the "use" parameter. Something like this:
Use      string `json:"use"`
  1. Then, I would filter out keys based on key.Use inside of this loop:

    keyfunc/jwks.go

    Lines 73 to 75 in 924bd5b

    for _, key := range rawKS.Keys {
    var keyInter interface{}
    switch keyType := key.Type; keyType {
  2. Write tests to cover the new code.

As a bonus, I would keep track of keys that have an incorrect "use" value in a separate field map[string]string, which would need a sync.RWMutex. This map would be used in the private method JWKS.getKey. If the kid matched a key in that map, I'd format an exported error type ErrJWKUse so the programmer knew why their key was rejected. If this wasn't included, it would be ErrKIDNotFound, which could get confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants