Description
Summary
When I enable global method security on an app that already subclasses WebSecurityConfigurerAdapter
, the application context fails to load in my test environment, with the message that the AuthenticationManager
was already built.
Actual Behavior
I have a vacuous test class that is just intended to check if the application context is loading properly:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=ShibaApplication.class)
@WebAppConfiguration
public class ShibaApplicationTests {
@Test
public void contextLoads() {}
}
(I have other test classes of course, and they fail with the same error.)
When I add the annotation @EnableGlobalMethodSecurity(prePostEnabled=true)
to an existing (working) subclass of WebSecurityConfigurerAdapter
and add a @PreAuthorize
annotation to any of my controller classes, my test classes fail (including the vacuous one above). The stack trace is enormous, but the outermost thread gives the following cause (linebreaks added):
Caused by:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'channelMarksController' defined in file [/Users/jason/Code/shiba/build/classes/main/co/masslab/shiba/transfer/ChannelMarksController.class]:
Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]:
Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]:
Factory method 'methodSecurityInterceptor' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'webSecurityConfig':
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private com.auth0.spring.security.auth0.Auth0AuthenticationFilter co.masslab.shiba.WebSecurityConfig.auth0Filter;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'auth0Filter':
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private org.springframework.security.authentication.AuthenticationManager com.auth0.spring.security.auth0.Auth0AuthenticationFilter.authenticationManager;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'authenticationManager' defined in class path resource [org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.class]:
Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]:
Factory method 'authenticationManager' threw exception;
nested exception is org.springframework.security.config.annotation.AlreadyBuiltException:
This object has already been built
Interestingly, outside of the test environment, the app runs without error and the @PreAuthorize
annotation even works as expected.
Expected Behavior
I expect the application context to load successfully within the test environment.
Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private Auth0AuthenticationEntryPoint auth0EntryPoint;
@Autowired
private Auth0AuthenticationFilter auth0Filter;
@Autowired
private Auth0AuthenticationProvider auth0AuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().hasRole("USER")
.and()
.exceptionHandling().authenticationEntryPoint(auth0EntryPoint)
.and()
.addFilterAfter(auth0Filter, SecurityContextPersistenceFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(auth0AuthenticationProvider);
}
}
Version
The app uses Spring Boot v1.3.3 BOMs. The observed issue is also present using Spring Boot v1.3.2 BOMs.
Sample
The project in question is private, but I have privileges sufficient to add individuals as contributors. Please contact me directly @whittle for access.