0

I have a Spring Boot web application that uses Spring Security. The index.html page contains a method call (POST) to the controller that loads objects from MongoDB into a ArrayList and returns it so it can be displayed on the front page.

It seems like Spring Security is preventing POST requests for anonymous users. If I first login so the "/loadContent" method is called, and thereby log out, everything works well. I do pass the CSRF tokens before calling the method.

My "WebSecurityConfig":

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/", "/loadContent")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll()
            .and()
            .exceptionHandling()
            .accessDeniedPage("/403");
}
trashy
  • 1
  • 1

2 Answers2

0

CSRF is enabled by default in spring security.

A possible solution is to disable it manually (see last line in code below).

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/", "/loadContent")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll()
            .and()
            .exceptionHandling()
            .accessDeniedPage("/403")
            .and().csrf().disable();
}

Update:

If you want to use csrf, which I encourage, maybe think about securing an additional REST endpoint e.g. starting with /api/.

In the example below these endpoints are secured using Basic Authorization with a user called api, but you can easily change it to allow anonymous users to request to resources:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
     @Autowired
     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("api").password("api").roles("API").and()
                .withUser("user").password("user").roles("USER").and()
                .withUser("admin").password("admin").roles("USER", "API", "ADMIN");
     }

     @Configuration
     @Order(1) // higher order = lower priority
     public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{

         @Override
         protected void configure(HttpSecurity http) throws Exception {
            // no csrf when communicating directly with the backend api
             http
                 .antMatcher("/api/**")
                     .authorizeRequests()
                         .anyRequest().hasAnyRole("API")
                         .and()
                 .httpBasic()
                 .and()
                 .csrf().disable();
             http.sessionManagement().disable();

         }
     }

     @Configuration
     @Order(2) // higher order = lower priority
     public static class UIWebSecurityConfig extends WebSecurityConfigurerAdapter {
       @Override
        protected void configure(HttpSecurity http) throws Exception {
           http.authorizeRequests() 
                .antMatchers("/**").hasAnyRole("USER", "ADMIN").anyRequest().authenticated();

           http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
           http.httpBasic().disable();
        }
     }
}
rocksteady
  • 2,320
  • 5
  • 24
  • 40
0

Turned to be a typo in the @RequestMapping area of the controller. Thank you very much for your assistance.

trashy
  • 1
  • 1