Spring Security 5 – Unable to start Spring Boot app configured with multiple external Authorization Servers if failed to connect to one Auth. Server

Background :

Configure Spring Boot Application to support Multiple External Authorization Servers

Example of application.properties :

#First Authorization Server

spring.security.oauth2.client.registration.my_okta_account.client-id=<client id>
spring.security.oauth2.client.registration.my_okta_account.client-secret=<client secret>
spring.security.oauth2.client.provider.my_okta_account.issuer-uri=<okta issuer>

#Second Authorization Server

spring.security.oauth2.client.registration.my_azure_ad.client-id=<client id> 
spring.security.oauth2.client.registration.my_azure_ad.client-secret=<client secret>
spring.security.oauth2.client.provider.my_azure_ad.issuer-uri=<azure ad issuer>

Problem Description :

At startup time Spring Boot will try to create a clientRegistrationRepository Bean based on the configuration info in the properties file for each Authorization Server and try to establish rest connection with it.

If Connection to External Authorization Server failed, Application will fail to start.

Error:
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

This is caused by : Caused by: java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "<azure ad issuer>" at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:220) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1] at org.springframework.security.oauth2.client.registration.ClientRegistrations.fromIssuerLocation(ClientRegistrations.java:144) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1] at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesRegistrationAdapter.getBuilderFromIssuerIfPossible(OAuth2ClientPropertiesRegistrationAdapter.java:83) ~[spring-boot-autoconfigure-2.4.5.jar:2.6.3]

This is caused by Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "< azure ad issuer >/.well-known/openid-configuration": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.6.jar:5.3.6] at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:670) ~[spring-web-5.3.6.jar:5.3.6] at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:155) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1]

This is a snippet of the method in org.springframework.security.oauth2.client.registration.ClientRegistrations that failed :


    private static Supplier<ClientRegistration.Builder> oidc(URI issuer) {
        // @formatter:off
        URI uri = UriComponentsBuilder.fromUri(issuer)
                .replacePath(issuer.getPath() + OIDC_METADATA_PATH)
                .build(Collections.emptyMap());
        // @formatter:on
        return () -> {
            RequestEntity<Void> request = RequestEntity.get(uri).build();
            Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();
            OIDCProviderMetadata metadata = parse(configuration, OIDCProviderMetadata::parse);
            ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer.toASCIIString())
                    .jwkSetUri(metadata.getJWKSetURI().toASCIIString());
            if (metadata.getUserInfoEndpointURI() != null) {
                builder.userInfoUri(metadata.getUserInfoEndpointURI().toASCIIString());
            }
            return builder;
        };
    }

ClientRegistrations.java can be found here : https://github.com/spring-projects/spring-security/blob/5.6.x/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/ client/registration/ClientRegistrations.java

The Line that failed is : Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();

Disclaimer :

As you might noticed this is a Certificate Exception and can easily be recovered by importing the root CA for

Question :

Is there a way to suppress this error and force Spring Boot App to start even if the configuration of one of the Authorization Servers failed to create the ‘clientRegistrationRepository’?

I tried to use Spring Lazy Initialization at the level of the Controller which depends on ‘clientRegistrationRepository’ Bean, but even if the controller is not yet initialized ‘WebMvcAutoConfiguration’ will try to instantiate the ‘clientRegistrationRepository’

Error: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setClientRegistrationRepository' parameter 0; nested exception is 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 < azure ad issuer />

My goal here is to successfully start the Spring Boot Application even if the connection to one of the External Authorization Server is not working.

Leave a Comment