Search code examples
spring-securityintegration-testingspring-security-test

Spring Security integration test for session authentication strategy


I have a Spring MVC + Spring Security Web application. The application has a custom session authentication strategy set up in the configuration

http.sessionManagement()
                .sessionAuthenticationStrategy( ... )

Since the strategy contains complex logic, it's important to test its behaviour via integrational tests.

When we use spring-security-test @WithMockUser the controller method is being called in tests, however our authentication strategy is not called.

What's the correct way to enforce full authentication process in Spring Security tests to ensure that session authentication strategy is indeed called?

Or to paraphrase: how to call the whole spring security filter chain?

Thanks for ideas.


Solution

  • In your integration test, supply a static WebSecurityConfigurerAdapter and it should get picked up.

    For example:

    @EnableWebSecurity
    static class CustomSessionAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .sessionManagement()
                    .sessionAuthenticationStrategy(customSessionAuthenticationStrategy);
        }
    }
    

    UPDATE:

    Here is a MockMvc test in Spring Security 4.x.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    @WebAppConfiguration
    public class SessionAuthenticationStrategyTest {
    
        @Autowired
        private WebApplicationContext context;
    
        private MockMvc mvc;
    
        @Before
        public void setup() {
            mvc = MockMvcBuilders
                    .webAppContextSetup(context)
                    .apply(springSecurity())
                    .build();
        }
    
        @Test
        public void requestWhenCustomSessionAuthenticationStrategyProvidedThenCalled() throws Exception {
            this.mvc.perform(formLogin().user("user").password("password"));
            verify(CustomSessionAuthenticationStrategyConfig.customSessionAuthenticationStrategy)
                    .onAuthentication(any(Authentication.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
        }
    
        @EnableWebSecurity
        static class CustomSessionAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter {
            static SessionAuthenticationStrategy customSessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class);
    
            @Override
            public void configure(HttpSecurity http) throws Exception {
                http
                    .formLogin()
                        .and()
                    .sessionManagement()
                        .sessionAuthenticationStrategy(customSessionAuthenticationStrategy);
            }
    
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth
                    .inMemoryAuthentication()
                        .withUser("user").password("password").authorities("ROLE_USER");
            }
        }
    }