Skip to content

Add option to use jwksCache in NimbusJwtDecoder #7639

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

Closed
wants to merge 1 commit into from

Conversation

nmz
Copy link

@nmz nmz commented Nov 8, 2019

Added option provide jwksCache so that the ttl can be configured

@pivotal-issuemaster
Copy link

@nmz Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@pivotal-issuemaster
Copy link

@nmz Thank you for signing the Contributor License Agreement!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 8, 2019
Copy link
Contributor

@jzheaux jzheaux left a comment

Choose a reason for hiding this comment

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

Thanks for the pull request, @nmz! I've left some feedback inline.


private JwkSetUriJwtDecoderBuilder(String jwkSetUri) {
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
this.jwkSetUri = jwkSetUri;
}

public JwkSetUriJwtDecoderBuilder jwkSetCache(JWKSetCache jwkSetCache) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer exposing an interface that is more powerful than the JWKSetCache interface. If an application really wants to supply a JWKSetCache, then it's quite simple to construct a DefaultJWTProcessor directly and pass that to the NimbusJwtDecoder constructor.

What if this took a org.springframework.cache.Cache instead? Then this builder could internally wrap that in a CacheJWKSetCache implementation, similar to the design of RestOperationsResourceRetreiver.

The nice thing about doing that is that an application can then use whatever caching mechanism they wish, be it Caffeine, Hazelcast, or something else.

Another nice this is that using Cache allows the entries to be key-value based which is better suited for a multi-tenant resource server that is caching keys from multiple issuers.

Copy link

@20fps 20fps Apr 3, 2020

Choose a reason for hiding this comment

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

@jzheaux Sry, but how should it help to multi-tenant resource server? I mean in multi-tenant environment we will have a separate AuthenticationManager for each tenant, that means for each tenant we will have: unique jwks-uri -> unique decoder -> so unique jwkSetCache, I don't see possible way for multiple keys to be stored in JWKSetCache with the current implementation

Copy link
Contributor

Choose a reason for hiding this comment

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

Good question, @20fps. I guess it comes down to what parts of your infra are multi-tenant. If your cache is multi-tenant, then each AuthenticationManager could have a JwtDecoder that shares the same cache - each JWK Set keyed, for example, by that tenant's JWK Set Uri.

If each tenant has its own cache, then that point is moot. My main point is that by introducing a key to the cache grants additional flexibility - multi-tenancy is one way that flexibility could be leveraged.

@@ -244,6 +244,12 @@ public void jwsAlgorithmWhenNullThenThrowsException() {
Assertions.assertThatCode(() -> builder.jwsAlgorithm(null)).isInstanceOf(IllegalArgumentException.class);
}

@Test
Copy link
Contributor

Choose a reason for hiding this comment

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

Please also add a unit test that confirms that the provided cache gets used.

@jzheaux jzheaux added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: waiting-for-feedback We need additional information before we can continue type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 18, 2019
@jzheaux
Copy link
Contributor

jzheaux commented Nov 20, 2019

@nmz are you able to apply the changes requested?

@andersflemmen
Copy link

@jzheaux if you want the same setup as with the NimbusJwtDecoder, but be able to set the cache time, it's not really just as simple as using the DefaultJwtProcessor though? Why shouldn't it be possible to set the cache time directly? 5 minutes is a pretty short default cache lifespan.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Mar 27, 2020
@jzheaux
Copy link
Contributor

jzheaux commented Mar 27, 2020

Good questions, @andersflemmen. Let's see if I can address a couple of them.

Why shouldn't it be possible to set the cache time directly?

Spring Security favors exposing components over individual properties. Consider, for example, a related use case of changing the socket timeout for the JWK Set request. Instead of exposing a method for changing the socket timeout, Spring Security exposes a method for supplying a custom RestOperations. This keeps the builder from getting cluttered with several small configuration options while at the same time giving the application a great deal of configuration power.

That said, another route could be to introduce a more generic builder - NimbusJwtDecoder.withJwkSource(JWKSource) - similar to the one that NimbusReactiveJwtDecoder already has. In that case, the application could instantiate its own JWKSource:

@Bean 
JwtDecoder jwtDecoder() {
    JWKSource<SecurityContext> jwkSource = new RemoteJWKSet(url, retriever, cache);
    return NimbusJwtDecoder.withJwkSource(jwkSource).build();
}

NimbusJwtDecoder.withJwkSetUri(String) could be enhanced to delegate to this builder.

5 minutes is a pretty short default cache lifespan.

This would be something to take up with the Nimbus folks. Perhaps they'd accept a pull request to lengthen the default ttl.

@andersflemmen
Copy link

@jzheaux Thank you for clarifying, that makes sense. Would be nice to see either this pull request completed, or an withJwkSource option.

@jzheaux
Copy link
Contributor

jzheaux commented Apr 10, 2020

Closed in favor of #8332

@jzheaux jzheaux closed this Apr 10, 2020
@rwinch rwinch added status: duplicate A duplicate of another issue and removed status: feedback-provided Feedback has been provided labels Apr 13, 2020
@jzheaux jzheaux added this to the 5.4.0-M1 milestone Aug 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants