10

I developed an application with spring boot, which was working fine. There is a restful controller. I tried to add spring security to some of the pages. The rest controller's endpoint is

/api/greetings

I configured the security settings in the class below.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home","/api/greetings").permitAll()
                //.antMatchers("/api/greetings","").permitAll()//can't do this
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

Now, when I tried accessing the Rest endpoint, from a Rest-client(Postman), only the GET method is accessible and i am getting 403 Forbidden response if I try to POST, PUT or DELETE.

{
    "timestamp": 1467223888525,
    "status": 403,
    "error": "Forbidden",
    "message": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.",
    "path": "/api/greetings/2"
}

How do i solve this issue. I am new to Spring Security things.

Rajan
  • 1,501
  • 4
  • 21
  • 37
  • Since mine is a non-browser application, disabling csrf wouldn't hurt, and it worked for me. I was curious, what if i don't want to disable csrf, or if my application is also web application, I found this link. Haven't tried it though but will try soon. http://stackoverflow.com/questions/27182701/how-do-i-send-spring-csrf-token-from-postman-rest-client – Rajan Jun 30 '16 at 22:47

1 Answers1

11

UPDATE Answer

If you're using Spring security 4, you can disable specific routes easily

http.csrf().ignoringAntMatchers("/nocsrf","/ignore/startswith/**")

If not, you can enable/disable CSRF on specific routes using requireCsrfProtectionMatcher

http.csrf().requireCsrfProtectionMatcher(new RequestMatcher() {
    private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
    private RegexRequestMatcher apiMatcher = new RegexRequestMatcher("/v[0-9]*/.*", null);

    @Override
    public boolean matches(HttpServletRequest request) {
        // No CSRF due to allowedMethod
        if(allowedMethods.matcher(request.getMethod()).matches())
            return false;

        // No CSRF due to api call
        if(apiMatcher.matches(request))
            return false;

        // CSRF for everything else that is not an API call or an allowedMethod
        return true;
    }
});

ORIGINAL Answer

You got an error because CSRF handling is 'on' by default with Spring Security.

You can disabled it by adding http.csrf().disable();.

But really, would you leave your application unsecured? I invite you to read this article to protect your application against CSRF, even if your application is based on REST service and not form submission.

MGR
  • 286
  • 3
  • 5
  • Is there other way, without disabling the csrf? – Rajan Jun 29 '16 at 21:02
  • When I used http.csrf().disable(); it also disabled all authentication. – garthoid Mar 25 '18 at 20:54
  • If you want to use CSRF protection, then you will have to add a token to your HTTP POST requests. You can do this for example by adding a html input element of type "hidden" to the html forms. You can get the token from the CsrfTokenRepository. See https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#csrf-using – Devabc Jun 13 '19 at 21:06