Summary
Fail to start a Spring Boot Application configured with oauth2Login() and with multiple external Authorization Servers if the connection to one them failed at startup
Actual Behavior
[ (self-tuning)'] o.s.boot.SpringApplication : Application run failed
...........
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientRegistrationRepository' defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository]: Factory method 'clientRegistrationRepository' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of
...........
Caused by: java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "
Expected Behavior
Successfully start the Spring Boot Application even if the connection to one of the External Authorization Server is not working.
Configuration
application.properties `#First Authorization Server
spring.security.oauth2.client.registration.my_okta_account.client-id=
Second Authorization Server
spring.security.oauth2.client.registration.my_azure_ad.client-id=
Version
5.6
Comment From: sjohnr
@mohamadassaad thanks for reaching out, and sorry for the delay on responding to this. I was out on break and then very busy when I returned.
The class used by Spring Boot to perform this discovery is ClientRegistrations. This issue has been on our radar for some time, and you can follow the conversation on #8882. As mentioned in that link:
ClientRegistrationsis intended to be used as a utility/convenience class. It was designed to fulfill most use cases, however, it may not be suitable for certain use cases. For example, if the internal network traffic must be routed through a Proxy, you can bypass discovery by configuring theauthorization-uriandtoken-uriproperty instead of theissuer-uriproperty.
Most of the time, using the discovery mechanism is a convenience, so I strongly recommend you try the above workaround as it will most likely work for you. Sadly, we may not have a better solution for quite some time until 5.8 and 6.0 are released.
I'm going to close this as a duplicate of #8882.
Comment From: ThanKarab
Hello @sjohnr , I am having the same issue with the latest version of spring security and keycloak (I don't think that it's relevant). I am trying to have a no-auth development deployment.
I tried to add the authorization-uri and the token-uri but then the resource server could not validate the token.
It only worked when I added the user-info-uri and jwk-set-uri as well.
The final problem that I am dealing with now is that the logout doesn't work.
Normally the /logout action would redirect to the ..../protocol/openid-connect/logout but when I don't set the issuer-uri it redirects to the postSuccessUrl.
Any ideas?
Comment From: sjohnr
@ThanKarab, thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it).
Comment From: ThanKarab
Thanks for the quick reply @sjohnr , any progress or walkthrough on how to use ClientRegistrations when the IP is offline?
Comment From: sjohnr
@ThanKarab, please see this comment.
Comment From: ThanKarab
I managed to find a workaround because since it's for development purposes I know when the identity provider server will not exist.
I am using the authentication enabled property with a conditional bean that creates a dummy clientRegistrationRepository. That way the lookup doesn't take place.
@Bean
@ConditionalOnProperty(prefix = "authentication", name = "enabled", havingValue = "false")
public ClientRegistrationRepository clientRegistrationRepository() {
ClientRegistration dummyRegistration = ClientRegistration.withRegistrationId("dummy")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.build();
return new InMemoryClientRegistrationRepository(dummyRegistration);
}