coffeLord February 2016

CSRF Token not accepted (Spring)

I run into a problem when adding CSRF to my existing and working CORS configuration.

Everytime a POST, PUT or DELETE is triggered I get the error that the current token I have is not the right one (nvalid CSRF Token 'edff86dc-093a-4df9-8218-e5343506bdf9' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.).

But when I compare them it can't be caused by the tokens. Also if i trigger a GET after that (e.g. PUT) the token before is sent again and accepted.

So I assume there might be a problem with my security config but I don't see what I'm missing.

security config:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
    http.authorizeRequests()
    .antMatchers(HttpMethod.OPTIONS, "/*/**").permitAll()
    .antMatchers("/logout", "/admin/**").authenticated();
    http.csrf().ignoringAntMatchers("/guestbook/**");
    http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
    http.formLogin().successHandler(authenticationSuccessHandler);
    http.logout().logoutSuccessHandler(logoutSuccessHandler);
    http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}

token filter:

public class CsrfTokenResponseHeaderBindingFilter extends OncePerRequestFilter {
protected static final String REQUEST_ATTRIBUTE_NAME = "_csrf";
protected static final String RESPONSE_HEADER_NAME = "X-CSRF-HEADER";
protected static final String RESPONSE_PARAM_NAME = "X-CSRF-PARAM";
protected static final String RESPONSE_TOKEN_NAME = "X-CSRF-TOKEN";

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, javax.servlet.FilterChain filterChain) throws ServletException, IOException {
    CsrfToken token = (CsrfToken) request.getAttribute(REQUEST_ATTRIBUTE_NAME);
    System.out.println(token.getToken());
    if (token        

Answers


coffeLord February 2016

So I finally solved my problem. After a lot of seach and error I discovered the CsrfProtectionMatcher which can be used to enable CSRF on different paths.

Anyways this was very confusing to me, because I thought CSRF would be a always enabled on every request by default. So as soon as I applied the CsrfProtectionMatcher on my "/admin" path (allowing all possible methods, which is specified as null) it worked. requireCsrfProtectionMatcher on docs.spring.io , detailed article

Also it's now possible for me, to work with a more simple configuration but despite that my old one works too.

old one with CsrfProtectionMatcher :

protected void configure(HttpSecurity http) throws Exception {
    RequestMatcher csrfRequestMatcher = new RequestMatcher() {

        private RegexRequestMatcher requestMatcher =
                new RegexRequestMatcher("/admin", null);

        public boolean matches(HttpServletRequest request) {

            if(requestMatcher.matches(request))
                return true;

            return false;
        }

    };      

    http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
    http
    .csrf()
        .requireCsrfProtectionMatcher(csrfRequestMatcher);
    http.authorizeRequests()
    .antMatchers(HttpMethod.OPTIONS, "/*/**").permitAll()
    .antMatchers("/login", "/**/**/**").permitAll()
    .antMatchers("/logout", "/admin/**").authenticated();
    http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
    http.formLogin().successHandler(authenticationSuccessHandler);
    

Post Status

Asked in February 2016
Viewed 2,760 times
Voted 14
Answered 1 times

Search




Leave an answer