Kaushik Balasubramanain
Kaushik Balasubramanain

Reputation: 1258

Spring Security CookieBasedCSrf not working

I am developing a RESTful Spring backend with an Angular2 front end. I store my access token (JWT implementation) in a httpOnly Cookie. To protect myself from XSRF attacks on post requests, I need to enable XSRF protection on all pages, except the login page. Per the Spring Security guide here, I have enabled CookieCsrfTokenRepository.

However, when I hit a public API (GET), the XSRF-TOKEN is not set. Also, when I submit my login form data from Angular2, the system thows a 'invalid csrf token' error. Below is my WebSecurityConfig:

    http
       .csrf()
           .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
           .and()
       .exceptionHandling()
           .authenticationEntryPoint(this.authenticationEntryPoint)
           .and()
       .sessionManagement()
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
           .and()
       .authorizeRequests()
           .antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point
           .antMatchers(TOKEN_CSRF_ENTRY).permitAll()
           .and()
       .authorizeRequests()
           .antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points
           .and()
       .cors()
           .and()
       .addFilterBefore(buildAjaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
       .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);

Upvotes: 1

Views: 3897

Answers (2)

Fan Jin
Fan Jin

Reputation: 2460

Have you tried to enable withCredentials: true? This is how I write my post server in Angular2.

this.http.request(
  path,
  {
    method: RequestMethod.Post,
    body: body,
    headers: customHeaders,
    withCredentials: true
  }
)
.map...
.catch...

I have the same config in WebSecurityConfig. I do have a working example using Angular 2 and Spring Boot that uses CookieCsrfTokenRepository.

My Angular 2 API service

My WebSecurityConfig

Github repo: angular-spring-starter

Upvotes: 0

dur
dur

Reputation: 17008

You should not get a CSRF token by HTTP GET, see Spring Security Reference:

Use proper HTTP verbs

The first step to protecting against CSRF attacks is to ensure your website uses proper HTTP verbs. Specifically, before Spring Security’s CSRF support can be of use, you need to be certain that your application is using PATCH, POST, PUT, and/or DELETE for anything that modifies state.

This is not a limitation of Spring Security’s support, but instead a general requirement for proper CSRF prevention. The reason is that including private information in an HTTP GET can cause the information to be leaked. See RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI’s for general guidance on using POST instead of GET for sensitive information.

You should not exclude login from CSRF protection, see Spring Security Reference:

Logging In

In order to protect against forging log in requests the log in form should be protected against CSRF attacks too.

But you can exclude some URLs from and include some HTTP verbs to CSRF protection, see Spring Security Reference:

You can also specify a custom RequestMatcher to determine which requests are protected by CSRF (i.e. perhaps you don’t care if log out is exploited). In short, if Spring Security’s CSRF protection doesn’t behave exactly as you want it, you are able to customize the behavior. Refer to the Section 41.1.18, “<csrf>” documentation for details on how to make these customizations with XML and the CsrfConfigurer javadoc for details on how to make these customizations when using Java configuration.

Upvotes: 1

Related Questions