8

I am unable to update my spring boot app to 2.6.0 from 2.5.7. It throws the following error.

2021-12-07T08:40:22,311 ERROR [restartedMain] o.s.b.SpringApplication.reportFailure:819|| Application run failed org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'webSecurityConfig': 
The requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227)

From the spring-boot 2.6.0 release notes, it is clear that circular references are disabled. And it can be enabled back with the property spring.main.allow-circular-references = true. But I would like to fix the circular reference in the first place. Can anyone help me troubleshoot this issue? Please find the WebSecurityConfig class below,

@Configuration
@EnableWebSecurity
@SuppressWarnings({"PMD.SignatureDeclareThrowsException"})
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsService userDetailsService;

    public WebSecurityConfig(final UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public BCryptPasswordEncoder bcryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/resources/**", "/registration", "/css/**", "/js/**", "/h2-console/*").permitAll()
                    .anyRequest().authenticated().and()
                .formLogin()
                    .loginPage("/login").permitAll().and()
                .headers()
                    .frameOptions().sameOrigin().and()
                .logout()
                    .permitAll().and()
                .requiresChannel()
                    .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                    .requiresSecure();
    }

    @Autowired
    public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bcryptPasswordEncoder());
    }
}

My code is open-sourced and can be found at https://github.com/surajcm/Poseidon, I will try to troubleshoot on my own and will share the updates if I am able to resolve this issue

Suraj Muraleedharan
  • 1,154
  • 2
  • 16
  • 30
  • this class looks fishy, custom security is bad practice https://github.com/surajcm/Poseidon/blob/2ad9e69c6ffbc7e860706040c4c616316878ba53/src/main/java/com/poseidon/user/service/SecurityService.java you should not be injecting the entire websecurityconfig also the override of "configureGlobal" is not needed, the encoder is a bean, and your userdetailsservice is a bean and will get picked up automatically. No need to set them manually. This is fully documented in the official documentation. – Toerktumlare Dec 07 '21 at 06:00

3 Answers3

17

The problem is the password encoder. It is required to build the auto-configured UserDetailsService that you inject in the contructor of the class.

You can break the cycle by making the bean factory method static:

@Bean
public static BCryptPasswordEncoder bcryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

You can also move the factory method to different configuration class. But in my opinion, your WebSecurityConfig is the canonical place for the method.

Henning
  • 3,055
  • 6
  • 30
  • 1
    See also the accepted answer in https://stackoverflow.com/questions/70073748/i-cant-update-my-webapp-to-spring-boot-2-6-0-2-5-7-works-but-2-6-0-doesnt – Kike Lebowski Feb 06 '22 at 10:55
0

Since I got a comment saying I am doing custom security config, which is a bad practice, I tried to fix it on my own. Tried to remove the configureGlobal and added authenticationProvider bean instead. Please find the sample code below

@Configuration
@EnableWebSecurity
@SuppressWarnings({"PMD.SignatureDeclareThrowsException"})
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsService userDetailsService;

    public WebSecurityConfig(final UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public BCryptPasswordEncoder bcryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        //http.headers().frameOptions().disable();
        http.csrf().disable();
        http
                .authorizeRequests()
                .antMatchers("/resources/**",
                        "/registration",
                        "/css/**", "/js/**", "/img/**",
                        "/h2-console/**",
                        "/console/**").permitAll()
                .and().headers().frameOptions().sameOrigin();
        http
                .authorizeRequests()
                .anyRequest().authenticated().and()
                .formLogin()
                .loginPage("/login").permitAll().and()
                .headers()
                .frameOptions().sameOrigin().and()
                .logout()
                .permitAll().and()
                .requiresChannel()
                .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                .requiresSecure();
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        var provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(bcryptPasswordEncoder());
        return provider;
    }
}
Suraj Muraleedharan
  • 1,154
  • 2
  • 16
  • 30
0

I got a similar error and the cause was that both spring-security-config version 5 and 4 were on the classpath. Check/refresh/correct your dependencies.

Pierre C
  • 2,920
  • 1
  • 35
  • 35