1

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.

leokom
  • 1,862
  • 1
  • 15
  • 26

1 Answers1

1

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");
        }
    }
}
leokom
  • 1,862
  • 1
  • 15
  • 26
Joe Grandja
  • 618
  • 4
  • 12
  • unfortunatel it's not getting picked up. By that I mean: onAuthentication method of SessionAuthenticationStrategy is not called. It looks like WithMockUser prevents the authentication chain to be invoked. Maybe WithMockUser is a bad idea here and I have to enforce authentication process somehow more manually? – leokom Dec 07 '18 at 07:30
  • important detail: Spring Security 4 is used in the project – leokom Dec 07 '18 at 07:33
  • Can you provide a sample of your test so I can see why it's not getting picked up. – Joe Grandja Dec 07 '18 at 19:44
  • thanks I'll try your suggestion, and post the sample if it won't work - on Monday when I have access to the code – leokom Dec 08 '18 at 20:03
  • your code indeed works well! (assuming we replace "{noop}password" with "password"). My code which depends on a lot inheritance of configurations still doesn't work. I'll try to converge my code as much as possible to your working example and provide more details in any case. Thank you! – leokom Dec 10 '18 at 16:47
  • thank you Joe! Your solution works indeed. Marked as accepted answer. The problem in my code was the fact that formLogin wasn't registered in HttpSecurity (because we use Tomcat SSO which is responsible for logging in). After formLogin registration, custom session authentication strategy works in the test – leokom Dec 11 '18 at 11:16