Creating a custom Bean of type OAuth2AuthorizedClientManager inside a class extending WebSecurityConfigurerAdapter and injection this bean somewhere in the application creates a circular reference.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,
                                                               OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {
    OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
      .authorizationCode()
      .refreshToken()
      .build();

    AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
      clientRegistrationRepository, oAuth2AuthorizedClientService);
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    return authorizedClientManager;
  }
}
@Service
public class MyBean {

  private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;

  @Autowired
  public MyBean(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
    this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager;
  }
}

How to reproduce?

  • Download https://github.com/knoobie/spring-2.5-oauth2manager-demo
  • Compile the application with mvn clean install
  • Test failed
Log

java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myBean' defined in file [/home/knoobie/projects/bugs/spring-2.5-security-demo/target/classes/com/example/demo/MyBean.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is 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 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is 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 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: 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 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?

Workaround:

  • Create the OAuth2AuthorizedClientManager bean in another class annotated with @Configuration.

Comment From: wilkinsona

Thanks for the sample.

Your SecurityConfig extends WebSecurityConfigurerAdapter which means that a ContentNegotiationStrategy bean should be injected into it. This bean is defined by Boot's EnableWebMvcConfiguration due to it sub-classing WebMvcConfigurationSupport which defines mvcContentNegotiationManager. To allow EnableWebMvcConfiguration to define this bean, it must be initialized and this requires the injection of any WebMvcConfigurer beans. OAuth2ClientWebMvcSecurityConfiguration is a WebMvcConfigurer so it needs to be initialized and this requires the injection of any OAuth2AuthorizedClientManager beans. Your SecurityConfig defines a OAuth2AuthorizedClientManager bean so it needs to be initialized but its initialization is already in progress. This is a circular reference so initialization fails.

I don't think there's anything that we can do about this in Spring Boot. Defining OAuth2AuthorizedClientManager in another @Configuration class is a good solution. Alternatively, I believe it would also work if the @Bean method was declared static as this would allow the OAuth2AuthorizedClientManager bean to be created without SecurityConfig having to be initialized.

You may also want to raise a Spring Security issue to see if they can remove some of the interdependencies between components so that user code is less likely to inadvertently create a circular reference.

Comment From: knoobie

Thanks @wilkinsona for your explanation!