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

Caching according to Okta guidance #5

Open
REASY opened this issue Jul 19, 2023 · 5 comments
Open

Caching according to Okta guidance #5

REASY opened this issue Jul 19, 2023 · 5 comments

Comments

@REASY
Copy link

REASY commented Jul 19, 2023

When an authorization server has been configured to rotate key credentials automatically, it is recommended to cache and dynamically fetch the public keys used to verify the signatures of tokens (returned in the JSON Web Key Store when calling the jwks_uri) received from the authorization server.

To avoid verification failure when keys are automatically rotated, Okta recommends the following:

  1. Cache the JSON Web Key Set (JWKS) indefinitely.
  2. When a token presents a 'kid' that is not recognized by the cache, the jwks_uri should be re-requested and re-cached.
  3. As an alternative to Step 2 above, another approach is to request the jwks_uri once per month. If there is a 'kid' mismatch, recache the keys.

Source: What is the recommended approach to take when caching the Okta JSON Web Keys Set(JWKS) for OAuth?

@06chaynes
Copy link
Owner

The cache mechanism respects the cache control directives sent by Okta, so far that seems to work fine.

Have you experienced any cache related issues after key change/rotation?

@REASY
Copy link
Author

REASY commented Jul 21, 2023

Hello, @06chaynes

I didn't see any specific code that pulls keys again if kid is not found. Looked at the code and my understanding with disk-cache feature it creates client

// Builds a surf client configured to use a disk cache
#[cfg(feature = "disk-cache")]
fn build_client() -> surf::Client {
    surf::Client::new().with(Cache(HttpCache {
        mode: CacheMode::Default,
        manager: CACacheManager::default(),
        options: HttpCacheOptions::default(),
    }))
}

that uses HttpCache that caches requests according to http spec.

@06chaynes
Copy link
Owner

06chaynes commented Jul 21, 2023

The cache revalidation and refresh is handled by the library, I actually wrote http-cache at first for this library to use.

Some more info can be found here on that https://developer.okta.com/docs/concepts/key-rotation

One relevant portion from that page:
"To save the network round trip, cache the jwks_uri response locally with respect to the directives in the standard HTTP Cache-Control headers. The cache-control directives are relative to the time of the request. If you make a request as the safe cache period ends, Okta returns the no-cache directive to ensure that you don't cache keys that will soon expire"

The cache will need to be revalidated and will be determined to be stale, so a new request will be made which will update the cache.

Have you experienced issues caching the keys?

@REASY
Copy link
Author

REASY commented Jul 21, 2023

@06chaynes I have not experienced any issues, it's more a curiosity regarding a new key id sent from the client. It will fail it for some period of time until the cache is invalidated.

Another link from Okta Dev forum: https://devforum.okta.com/t/detect-when-jwk-keys-are-rotated/11764

Typically, we recommend that you do just as you’re doing now: caching the keys and waiting until you are sent a token with a ‘kid’ you don’t recognize before you cache them again.

@06chaynes
Copy link
Owner

06chaynes commented Jul 21, 2023

How long do you experience these failures before the cache is refreshed? Also is this after a normal key rotation?

I ask because in my tests rotating the key manually the cache was refreshed without failing for any period of time.

A request was prepared and sent which resulted in the keys being cached.

The keys were then rotated.

A second request was prepared, the cache sees the object in cache but in this case will require revalidation. A revalidation request is sent, which in this case will return a fresh response. The cache will be updated and the response returned.

There should be no failure during this time thanks to the headers okta sends for these events. If you can reproduce a problem though I can dig a bit deeper.

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

No branches or pull requests

2 participants