6

I want to disable csrf when doing integration tests for my springboot application. I have already tried security.enable-csrf=false but that doesn't seem to have any effect. I have also tried passing csrf token in my tests via SecurityMockMvcRequestPostProcessors.csrf method but to no avail.

In my application, there is custom SecurityConfig which extends WebSecurityConfigurerAdapter and has code something like this:

http
.csrf()                   .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeRequests()
.antMatchers(LOGIN_URL).permitAll()
.antMatchers("/api/v1/forgotpwd").permitAll()
.antMatchers("/api/v1/changepwd").permitAll()
.antMatchers("/api/v1/isLoggedIn").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.logout().logoutUrl("/api/v1/logout").deleteCookies("JSESSIONID").invalidateHttpSession(true)
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.and()
.addFilter(jsonUsernamePasswordAuthenticationFilter())
.addFilterAfter(new MDCEmailSetterFilter(),JsonUsernamePasswordAuthenticationFilter.class);

If I set http.csrf().disable(), my tests work and csrf token authentication failure does not happen otherwise it throws 403 with message that csrf token cannot be validated.

Any help?

Divick
  • 1,213
  • 1
  • 20
  • 44

2 Answers2

9

I was able to test my @WebMvcTest, doing this:

Import SecurityMockMvcRequestPostProcessors.* statically:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;

Then in your mockMvc request, you can use:

with(csrf())

In the end, your request will be like this:

        this.mockMvc
            .perform(post("/users").with(csrf())
                    .content(objectMapper.writeValueAsString(createUserDto))
                    .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
            .andExpect(status().isCreated());

The full explanation from Spring documentation can be found at

And as described in the second link

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

mlecar
  • 729
  • 6
  • 9
3
http.csrf().disable()

You can call it for tests profile only for example

@Value("${spring.profiles.active}")
private String activeProfile;

if (activeProfile.trim().equalsIgnoreCase("integrational-tests")) {
    http.csrf().disable();
}
Bohdan Petrenko
  • 997
  • 2
  • 17
  • 34
  • 1
    Yeah this works but a bit intrusive. I am clueless why SecurityMockMvcRequestPostProcessors.csrf method call doesn't work? – Divick Feb 06 '18 at 15:23