I think it would be useful to disable the OAuth2 / OIDC discovery explicitly. At this moment this is possible implicitly by configuring every necessary detail of the clients registration and provider but skipping the providers issuerUri. This disables the discovery via OAuth2ClientPropertiesMapper.
Why
- Someone wants the service to not require the IdP to be available at startup.
- Some code may need the
issuerUrito function properly.
In fact, there already is such code: Spring Securitys OIDC back channel logout validates the providers issuerUri in OidcBackChannelLogoutTokenValidator and ends up with a NPE if you did not set an issuerUri.
So setting the issuerUri means you are forced to use discovery.
Leaving it null means no working back channel logout, at least not with auto configuration.
How?
I'm not quite sure. Maybe a new property:
# default (fallback) value: true
spring.security.oauth2.client.provider.MY_PROVIDER.discovery=false
Setting this to false would opt-out the discovery. The current behaviour should be kept as default.
Comment From: knoobie
+1 / We also have strong requirements that systems should not depend on other systems while starting - so we are also forced to manually configure everything. This leads to interesting problems when e.g. the oauth provider changes something and our configuration gets out of date - which in turn creates hard to troubleshoot problem at first glance.
Comment From: wilkinsona
This leads to interesting problems when e.g. the oauth provider changes something and our configuration gets out of date
How would disabling discovery help with that? I don't understand how it would help to keep your configuration in sync with that of your OAuth provider.
Comment From: knoobie
How would disabling discovery help with that? I don't understand how it would help to keep your configuration in sync with that of your OAuth provider.
Good question, Andy! I went a little bit overboard and interpreted a bit too much into the issue, like e.g. true/false and "lazy" loading of the configuration - allowing the application to start, but retrieve the required information on first access.
Comment From: philwebb
@jgrandja do you have any thoughts on this suggested change?
Comment From: jgrandja
@delbertooo
Some code may need the issuerUri to function properly.
In fact, there already is such code: Spring Securitys OIDC back channel logout validates the providers issuerUri in OidcBackChannelLogoutTokenValidator and ends up with a NPE if you did not set an issuerUri
I can't recall, but the issuerUri may be required for the OIDC back channel logout. @jzheaux Would be able to answer this one.
Someone wants the service to not require the IdP to be available at startup.
The SupplierClientRegistrationRepository added in gh-12967 could solve this issue as the issuer lookup is deferred on first access.
@philwebb Maybe the solution is to wrap the InMemoryClientRegistrationRepository @Bean
https://github.com/spring-projects/spring-boot/blob/f78ec43dd61a202dd224637c375a0d64280e5bfc/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.java#L47
in a SupplierClientRegistrationRepository?
Comment From: jzheaux
Yes, the issuer URI is required for back-channel logout due to how ID Tokens are validated.
As a side note, it would certainly be reasonable to give a better error response. I've added https://github.com/spring-projects/spring-security/issues/15771 to address that.
Comment From: delbertooo
The
SupplierClientRegistrationRepositoryadded in gh-12967 could solve this issue as the issuer lookup is deferred on first access.@philwebb Maybe the solution is to wrap the
InMemoryClientRegistrationRepository@Beanhttps://github.com/spring-projects/spring-boot/blob/f78ec43dd61a202dd224637c375a0d64280e5bfc/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.java#L47
in a
SupplierClientRegistrationRepository?
@jgrandja Yes, this kind of works and is our current solution / workaround:
@Bean
public SupplierClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
return new SupplierClientRegistrationRepository(() -> {
log.info("Loading OAuth2 client registrations");
final var registrations = new OAuth2ClientPropertiesMapper(properties).asClientRegistrations();
return new InMemoryClientRegistrationRepository(registrations);
});
}
Works for some scenarios. Might break if one uses oauth2Login with the default generated login page, because the login page works with login links from the repository and is built at application boot. Therefore the application cannot boot without the provider.
This leads me to the question: is it desirable to configure a provider completely without the need of discovery? Or would it be more straight forward to have a local copy of the configuration metadata and use the discovery against the local file copy?
Comment From: jgrandja
@delbertooo
Might break if one uses
oauth2Loginwith the default generated login page
Yes, you are right, it would break if the provider configuration endpoint was not accessible at startup time. Although the generated login page is only meant to be used at development/test time and not production, we would need to ensure it doesn't break regardless.
is it desirable to configure a provider completely without the need of discovery? Or would it be more straight forward to have a local copy of the configuration metadata and use the discovery against the local file copy?
It depends on the requirements of your application environment. The way I see it is if your application needs access to the provider configuration endpoint then it needs to ensure the provider is up and running at startup. But if it needs to be more resilient at startup and not depend on the provider then you should be explicit on the provider configuration and not depend on issuer-uri or use SupplierClientRegistrationRepository.