MicahParks / keyfunc

Create a jwt.Keyfunc for JWT parsing with a JWK Set or given cryptographic keys (like HMAC) in Golang.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mix loading from JWKS URL with keys from JSON

sean-rn opened this issue · comments

commented

I have a use case where I would like to use the keys loaded from a JWKS URL in addition to a set of statically configured keys. (I believe supporting this sort of case is the intent of the GivenKeys option passed to Get())

I'd like to make my code more flexible by loading the statically configured keys from a static JWKS JSON.

I could parse the JSON myself and use the NewGivenXXXX functions, but that duplicates all of the work that keyfunc's NewJSON() function already does. It feels simpler and more forward-compatible if I could use keyfunc to parse the static JWKS JSON into a map I can use as the GivenKey's option to Get().

However, if I try to construct a string[map]keyfunc.GivenKey from the JWKS instance provided by NewJSON()... I can try to use ReadOnlyKeys(), but then I run into the alg issue again.

A few possibilities which keep the public API clean

  1. A method on JKWS which returns a map of GivenKeys suitable for passing as an option to Get(): func (j *JWKS) AsGivenKeys() map[string]GivenKey
  2. A new exported function which parses a JWKS JSON into a map of GivenKeys suitable for passing as an option to Get(): func NewGivenKeysFromJSON(jwksBytes json.RawMessage) (map[string]GivenKey, error)

Both of these keep the mechanics of how the GivenKey instances are created internal to the package† (so if another situation like needing to add alg happens in the future it can be transparently applied to this function as well)

Any other ideas for helping my use case?
Note: Something like the multiple source feature proposed in #72 might also be adapted for this, but the existing Options.GivenKeys field already perfectly fits this use case and already has provisions for handling KID conflicts.

†Which my earlier KeyAlg() method did not.

Thank you for opening this issue, @sean-rn.

I think it's a good idea to support this use case. I particularly like suggestion 2 because it completely independent of keyfunc.Get's "background goroutine". And does not allow for any user error in modifying pointers still in use by keyfunc.

I may be able to think over this more and continue the discussion further after work, I am on EST time.

commented

Pseudocode for how to use these suggestions for my use case:
Option 1:

staticJwks, err := keyfunc.FromJSON(staticJSON)
staticKeys := staticJwks.AsGivenKeys()
combinedKeys, err := keyfunc.Get(jwksURL, keyfunc.Options{GivenKeys: staticKeys})

Option 2:

staticKeys, err := keyfunc.NewGivenKeysFromJSON(staticJSON)
combinedKeys, err := keyfunc.Get(jwksURL, keyfunc.Options{GivenKeys: staticKeys})

I like option 2, which is what I think the linked PR has.

PR looks good!

The PR was perfect! Thank you for included tests too.

You can use the new release with the v1.7.0 tag.