CSRF Protection with Spring Security and Angular JS

Both Spring Security and Angular JS provide support for CSRF protection. However, getting these to work together to provide protection from CSRF requires some non-obvious configuration. This blog post explains how to add CSRF protection to an application that uses Spring Security with an Angular JS front end.

Cross-Site Request Forgery (CSRF) 1 is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. This blog post implements the CSRF token part of the protection described by OWASP. The application still needs to have protection to enforce the right Origin for requests.

Front end

For this example, we will build a simple Spring Boot application with an Angular front end. The front end is based on the application we built for the series on authentication with JWT. The changes are in how the initial authentication is done - we will be using Basic Auth in this example to perform the initial authentication.

Security

In this example, we will be using an in-memory authentication. We will also be using a header based session instead of a Cookie based session by wiring up HeaderHttpSessionStrategy. Sessions are stored in-memory using MapSessionRepository. We also secure all end points except the front end components and the /login end point.

Protecting URLs selectively

We want a mechanism to specify a list of URL patterns for which CSRF protection need to be turned OFF. Spring Security provides a requireCsrfProtectionMatcher method. With this, we will add a matcher that returns false when any of the URL patters we have matches the current request’s path.

But we do not see anything in the response that tells the client what the token allocated to it for the current session is. This is because Spring Security’s CSRF protection by default provides enforcement and allocation of tokens, but it does not expose the token granted to the client out of the box.

Granting CSRF Token to the client

One way to grant the client the CSRF token allocated to the current session will be to add a filter that sets the token as a Cookie once it is available. For this, we will add a filter immediately after the session is assigned by Spring Security’s SessionManagementFilter.

The filter checks to see if the current request has a CSRF token set on it by Spring Security’s CsrfFilter and then sets it as a Cookie on the response, if the current request was made by a client to authenticate.

With this filter in place, when we authenticate, we will see the following behavior:

We can clearly see that the CSRF token is sent to the client as a Cookie. At this point, we can make changes to our front end to send this token with every subsequent request. However, it is easier to use Angular’s support for CSRF tokens.

Customizing CSRF protection for Angular

Angular’s CSRF protection 2 uses the cookie XSRF-TOKEN it expects from server responses and the header X-XSRF-TOKEN which it will send for every subsequent request, once the Cookie is found in a response. We will have to configure Spring Security to use this header and token instead of it’s default header X-CSRF-TOKEN and Cookie name CSRF-TOKEN.

The first step is to pass Spring Security a custom CsrfTokenRepository:

With these configurations in place, the front end is able to authenticate and obtain a token Cookie which Angular will pass for every subsequent request.

Configuring order of enforcement

The only drawback to the configurations we have developed so far is that when a client makes a request to a protected end point with out Authentication and CSRF token, it will receive a 403 Forbidden instead of a 401 Unauthorized.

If this is not the behavior desirable for your application, we can disable the default CSRF protection and enable the required filters, enforcing the right order. This is achieved with the following configuration: