How to configure Spring Security to send 'X-CSRF-TOKEN'?

All we need is an easy explanation of the problem, so here it is.

The problem is to get the CSRF tokens working between Spring Security and Angular.

Spring Security CSRF Token Interceptor for Angular seems like something that should do the job, but there is no ‘X-CSRF-TOKEN’ in the HEAD response from the server.

My current tiny implementation is available in GitHub (Tag v.1.0) and I would appreciate a lot if somebody who knows the topic would have a quick look on the code, the problem should be easy to spot.

Based on the documentation, I am under the impression that CSRF should have been enabled automatically, but that seems not to be the case.

I am using Spring Boot and prefer the annotation-based configuration over XML, if something needs to be configured differently.

Any other approaches to make Spring Security work against Angular?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Angular looks for a cookie called “XSRF-TOKEN” I believe, so the easiest thing to do for the client is to send that. You can do it in a Filter for instance (example from https://github.com/spring-guides/tut-spring-security-and-angular-js/blob/master/single/src/main/java/demo/UiApplication.java#L65):

    private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request,
                    HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                        .getName());
                if (csrf != null) {
                    Cookie cookie = new Cookie("XSRF-TOKEN", csrf.getToken());
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
                filterChain.doFilter(request, response);
            }
        };
    }

Update: since spring security 4.2 the correct cookie name for angular is used by default if you use the cookie csrf repository(the link is still the best source), i.e. there is no longer any need for a custom filter. Example:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                ...
                .and()
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

Method 2

I am answering the question myself as there was a hidden one in the original GitHub repository: Issue #1.

The solution was to add a couple of lines of Java code that adds the CSRF parameters as Http message headers.

I added a working solution to the GitHub repo with Tag v.2.0.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply