jwx: Add Expiration field for jwk.Set that is populated by cache-control header

Abstract It would be great if jwk.Set had an Expiration property that is populated by the HTTP cache-control header when FetchHTTP is used or can be set manually if one of the Parse methods is used. Additionally, an ‘Origin’ property to track where the jwk.Set originated from would be helpful (per the usecase below)

Describe the proposed solution/change Before enumerating available Keys in a Set, one could:

  if set.IsExpired() {
    set, err := set.Refetch()
    if err != nil {
      log.Printf("failed to refetch expired JWKS: %s", err)
      return
    }
  }

Analysis Since FetchHTTP methods do not make any of the server’s headers available to the caller, the only currently alternative is to re-implement FetchHTTP outside of jwx.

Additional context Happy to provide a PR if the maintainers agree it would be useful.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18

Most upvoted comments

I need to jet for the day, but going to leave the following memo for me to remember later:

Possible idea. Use github.com/gregjones/httpcache underneath, but add a higher level API like so:

// * Deprecate jwk.FetchXXXX
// * Add storage (or source?) object(s), which knows how to fetch and cache jwk keys.
//        * This may be tricky if we're going to allow both HTTP and filesystem
//.          from the same API
store := NewMemoryStore(
  WithMinimumRefreshInterval(15*time.Minute), // only refresh if the cache object's age is greater than 15 minutes
)
keyset, err := store.Fetch(url) // first time, or when you don't care if the keyset is overwritten

// refresh jwk only if jwk has been updated, check against cache-control/expires
// second argument must be a pointer to key or keyset 
store.Refresh(jwkurl, interface{}, options...)

re: synchronization, am pretty sure something like this will avoid a thundering herd https://github.com/lestrrat-go/jwx/commit/5eefc72703b0225e3b1390fa1eb5649dd369e641