-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Register RestOperations @Bean to be used as default for oauth2-client flows #5607
Comments
I'm not sure we should be quite as granular as springSecurityOAuth2RestOperations. Otherwise we run into a pretty slippery slope on bean names. Do we add springSecurityOAuth2ClientRestOperations, springSecurityOAuth2ResourceServerRestOperations, etc? Likely springSecurityRestOperations is good enough or potentially even just a Bean rather than the name. |
I'm fine with
How do we know |
Instead of registering a well-known For the For example, public interface JwtDecoderFactory<C> {
// context - provides contextual information used to create a specific JwtDecoder
JwtDecoder createDecoder(C context);
}
public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<ClientRegistration> {
@Override
public JwtDecoder createDecoder(ClientRegistration clientRegistration) {
....
} We could have a similar design for creating public interface RestOperationsFactory<C> {
// context - provides contextual information used to create a specific RestOperations
RestOperations createRestOperations(C context);
}
public final class OAuth2ClientRestOperationsFactory implements RestOperationsFactory<ClientRegistration> {
@Override
public RestOperations createRestOperations(ClientRegistration clientRegistration) {
....
} If a user needs to provide a configured For example, the We'll need to figure out how to configure the |
Again I think this is too granular. We don't want to add factories for everything that can be created. |
@rwinch Can you elaborate why you think this design is too granular?
Why do you think a factory is not suitable here? FYI, we only have one factory defined in OAuth 2.0 codebase thus far - Is there another solution you have in mind that you can propose? |
If you are creating Perhaps we could allow users to define their own Alternatively, I could see looking for a RestTemplate as a default for all of Spring Security, but I don't want to have custom factories for each Bean |
Registering
Ok, so it sounds like you are favouring a well-known bean name, as per comment? |
Yes. Can we just have a single well known bean name for all of security? I doubt that most setups will need multiple different RestTemplate instances. If they do, they can always define the beans explicitly |
one possible exception, tests. |
I don't have any strong opinions with regards to the design of the API, but we've met this obstacle while trying to customize the trust store to be used for the outgoing connection against the authorization server. After reading through the source, we found out that the RestTemplate instance was new'ed locally, and as far as we could tell, was not externally customizable. It was quite confusing to discover that the client used RestTemplate internally with one way of doing customization, while the the client we're using to do the actual API call is using WebFlux with another customization strategy :-/ a) Is there any known workarounds for doing this (apart from using the java command line option to set the trust store or change the "global" cacerts file) ? |
We also ran into a similar issue, when facing a http proxy to be configured. First, we simply put the Spring Security 5.2.2.RELEASE modules spring-security-oauth2-resource-server and spring-security-oauth2-jose into the classpath to get the default configurations. (Spring Boot 2.2.5.RELEASE) This lead to the following exception on startup, because the initial openid-configuration was not fetchable because of the companies internal http proxy.
Then we set the JVM arguments '-Dhttps.proxyHost' and '-Dhttps.proxyPort' which lead to a successful retrieval of the openid-configuration. Nonetheless, another error occured now at runtime, when an incoming token had to be validated. The NimbusReactiveJwtDecoder is trying to fetch the jwks using a WebClient.
The reason for this is that we are using Spring Cloud Gateway which requires Webflux. Now, with Webflux on the classpath, the reactive WebClient is initialized. In constrast to this, the initial retrieval went fine, because JwtDecoderProviderConfigurationUtils uses a RestTemplate which is applying the JVM args. The main problem here is as far as I can see that the Netty WebClient does not honor the JVM arguments. (reactor/reactor-netty#887 (comment)) So we had to configure the WebClient to be aware of the proxy. Unfortunately, the NimbusReactiveJwtDecoder is by default using a processor() with a web client created by WebClient.create() instead of using a pre-configured one. Thus in the end, we had to provide a fully customized decoder. We copied the default configuration procedure and applied builder.webClient(proxyWebClient()) on the builder. @Bean
public ReactiveJwtDecoder jwtDecoder() {
final Map<String, Object> configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForOidcIssuerLocation(oidcIssuerLocation);
JwtDecoderProviderConfigurationUtils.validateIssuer(configuration, oidcIssuerLocation);
final OAuth2TokenValidator<Jwt> jwtValidator = JwtValidators.createDefaultWithIssuer(oidcIssuerLocation);
final NimbusReactiveJwtDecoder jwtDecoder = withJwkSetUri(configuration.get("jwks_uri").toString())
.webClient(proxyWebClient())
.build();
jwtDecoder.setJwtValidator(jwtValidator);
return jwtDecoder;
} It would be really nice to make at least webClient(...) available to ReactiveJwtDecoders or NimbusReactiveJwtDecoder. The best option would be a spring-provided workaround for creating the WebClient or making the WebClient automatically aware of proxy arguments. |
One point here is that as the resource server can now support multiple tennants you may not want to use the same Rest Template for each issuer. You may have different setups for each one (different proxies, different security commections). I have made a draft PR to open it up. By no means do I think this is the correct solution, |
Closing in favour of #8882. Please provide any additional feedback there. |
We should register a
RestOperations
@Bean
inOAuth2ClientConfiguration
that is configured with default settings and is used as the default viasetRestOperations(restOperations)
in the variousoauth2-client
flows - see #5601.The well-known
@Bean
should be named springSecurityOAuth2RestOperations and automatically be injected/used as the default in alloauth2-client
flows. The user has the ability to register a@Bean
with the same name, which will effectively override the default.For now, the default
@Bean
will be configured with default connect and read timeout settings for 30 secs. However, the user may override this@Bean
and provide custom settings for Proxy, SSL, HTTP Client backing implementation, etc.The text was updated successfully, but these errors were encountered: