4

I'm trying to build an Angular 2 page on top of a Spring Boot API. I have configured CORS (correctly I believe), but I am getting blocked by Spring Security's CSRF protection.

It is my understanding that Angular 2 handles CSRF automatically as of RC2, and I am on RC4. The server is sending an XSRF token in response to a POST from the Client as seen here:

enter image description here

I assume that Angular 2 is not picking it up? I know that CORS is working because when I put .ignoringAntMatchers("/urlhere/") on the end of .csrf() to test, the request went through, so CORS is not blocking it. Here is my config method for HttpSecurity:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .authorizeRequests()
            .antMatchers("/auth/**", "/signup/**").permitAll()
            .and()
        .headers() 
            .and()
        .exceptionHandling()
            .and()
        .cors()
            .and()
        .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

}

My Login process on client side consists of a method that first sends credentials, then uses a JWT token to retrieve credentials. The two methods are as follows:

sendCredentials(model) {
   let tokenUrl = 'http://localhost:8080/user/login';
   let headers1 = new Headers({'Content-Type': 'application/json'});

   return this.http.post(tokenUrl, JSON.stringify(model), {headers: headers1});
}

sendToken(token){
   let userUrl = 'http://localhost:8080/rest/user/users';
   let headers2 = new Headers({'Authorization': 'Bearer '+token});

   return this.http.get(userUrl, {headers:headers2});
}

What am I missing to satisfy the requirements for CSRF protection? Is it client side? Or am I needing to add /login/ to my list of antMatchers?

1 Answer 1

3

I know it's late but, I ran into same problem and managed to solve it. Problem in angular http request:

return this.http.post(tokenUrl, JSON.stringify(model), {headers: headers1});

You need to adjust it to send like that :

return this.http.post(tokenUrl, JSON.stringify(model), {headers: headers1, withCredentials: true});

You have to add withCredentials: true to all your http requests. Why you need it? Each time you send http request(OPTIONS, POST etc) to Spring(server) it will generate new XSRF-TOKEN and issue it to client, withCredentials: true will save this new XSRF-TOKEN in browser and later on used for new http request, so in case one of your http requests doesn't have withCredentials: true it will simply ignore new XSRF-TOKEN and use old(expired) XSRF-TOKEN for http request.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer! It adds to the knowledge base, so I marked it as answered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.