AngularJS HTTP POST Expected CSRF token not found
<p>I was following the tutorial from Spring Blog (<a href="https://spring.io/guides/tutorials/spring-security-and-angular-js/" rel="nofollow">https://spring.io/guides/tutorials/spring-security-and-angular-js/</a>). But I started with an existing Spring application, therefore I am not using Spring Boot to start with and I have to find a way to implement the components in XML and Java Configuration hybrid style. </p>

<p>Here is my CORS filter:</p>

<pre><code>@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    public SimpleCORSFilter(){

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response=(HttpServletResponse) resp;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //x-auth-token is a custom header for Spring Security AngularJS implementation
        response.setHeader("Access-Control-Allow-Headers", "Options, authentication, authorization, X-Auth-Token, Origin, X-Requested-With, Content-Type, Accept, XSRF-TOKEN");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            System.out.println("OPTIONS request from AngularJS");
            response.setStatus(HttpServletResponse.SC_OK);
        }
        chain.doFilter(req, response);
    }

    @Override
    public void destroy() {}
</code></pre>

<p>and here is my CsrfHeaderFilter.java, pretty much just copied from the tutorial:</p>

<pre><code>@Component
public class CsrfHeaderFilter extends OncePerRequestFilter{

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        System.out.println("CsrfHeaderFilter vvv");
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        if(csrf != null){
            Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
            String token = csrf.getToken();
            System.out.println("CSRFToken Value: "+token);
            if(cookie == null || token != null &amp;&amp; !token.equals(cookie.getValue()) ){
                cookie = new Cookie("XSRF-TOKEN", token); //use XSRF-TOKEN as the response header for CSRF token
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }
        System.out.println("CsrfHeaderFilter ^^^");
        filterChain.doFilter(request, response);
    }
</code></pre>

<p>and CsrfHeaderFilter is configured to be after Spring's CsrfFilter:</p>

<pre><code>&lt;sec:custom-filter ref="csrfHeaderFilter" after="CSRF_FILTER" /&gt;
&lt;sec:csrf token-repository-ref="csrfTokenRepository"/&gt;
</code></pre>

<p>csrfTokenRepository:</p>

<pre><code>@Configuration
public class CustomCsrfTokenRepository {

    @Bean
    public CsrfTokenRepository csrfTokenRepository(){
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        repository.setParameterName("_csrf");
        return repository;
    }
}
</code></pre>

<p>I have my own Authentication Filter with a custom login URL:</p>

<pre><code>public class CustomerAuthenticationTokenProcessingFilter extends AbstractAuthenticationProcessingFilter{

    private static final String SECURITY_TOKEN_HEADER = "x-auth-token";
    private static final String AUTHORIZATION_HEADER = "authorization";

    @Autowired
    private CustomerTokenAuthenticationService tokenAuthenticationService;

    @Autowired
    CustomerAuthenticationService customerAuthenticationService;
    @Autowired
    @Qualifier("customerAuthenticationManager")
    AuthenticationManager authenticationManager;

    protected CustomerAuthenticationTokenProcessingFilter(){
        super("/company/login"); 
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
            Authentication authentication = null;
            //Authentication Logics...
            ...
        return authentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            Authentication authResult) throws IOException, ServletException {
        SecurityContextHolder.getContext().setAuthentication(authResult);
      }
}
</code></pre>

<p>and of course, a custom logout url:</p>

<pre><code>&lt;sec:logout invalidate-session="true" delete-cookies="JSESSION,XSRF-TOKEN" 
    logout-url="/resource/logout" success-handler-ref="customerLogoutSuccessHandler"/&gt;
</code></pre>

<p>customerLogoutSuccessHandler:</p>

<pre><code>public class CustomerLogoutSuccessHandler implements LogoutSuccessHandler{

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {

        if (authentication != null &amp;&amp; authentication.getDetails() != null) {
            try {

                SecurityContextHolder.clearContext();
                System.out.println("User Successfully Logout"); 
                response.setStatus(HttpServletResponse.SC_OK);

            } catch (Exception e) {  
                e.printStackTrace();  
                e = null;  
            }  
        }  
    }

}
</code></pre>

<p>The AngularJS code is pretty simple. Originally I show the login form and just do a HTTP POST request to the Spring's /company/login endpoint, but somehow my AngularJS application is not getting the CSRF token it needed... So i added a HTTP GET request at startup to request from an open URL (access="permitAll()") in order to get the XSRF-TOKEN for my upcoming requests. Login and logout works fine until I login again. The error is "POST <a href="http://localhost:8080/company/login" rel="nofollow">http://localhost:8080/company/login</a> 403 (Forbidden)" and "Invalid CSRF Token was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'"</p>

<p>I think there is something wrong with cookies in my browser. I can see the same XSRF-TOKEN from before being pass to Spring when I output the cookie data in my CORS filter, and Spring's CsrfFilter denied further request because the CSRF token is not correct.</p>

<pre><code>FilterChainProxy DEBUG - /company/login at position 3 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
CsrfFilter DEBUG - Invalid CSRF token found for http://localhost:8080/company/login
</code></pre>

<p>Maybe I am missing some functions on the logout part? How can i update the XSRF-TOKEN if my request never get pass Spring's CsrfFilter?</p>

<p>Please feel free to ask me for more detail if necessary. I really want to get this issue solved because I already spent so much time trying to figure out what is wrong :(</p>