Fix “Invalid CSRF token” error – add the XSRF-TOKEN header in Angular

feature image

Angular provides a built-in support for sending requests secured with the XSRF-TOKEN header. However, it won’t add the token to absolute URLs for security reasons. One way to solve the “Invalid CSRF token found” issue is to use relative links in all mutable requests and apply a custom proxy.

Debugging missing CSRF token

First, we have to be sure that Angular really doesn’t send requests with the X-XSRF-TOKEN. In the following section I’ll show you how to debug a Spring Boot application.

Adjust debug level on security logs

In order to see more detailed logs and enable security debugging add the following line to your application.properties file:

As a result, after restarting the app, you’ll be able to read messages logged by the CsrfFilter class:

Add a breakpoint

Now you know exactly where to set a breakpoint. In other words, add it in the CsrfFilter::doFilterInternal method (package: org.springframework.security.web.csrf) and verify that the actualToken is indeed null:

A breakpoint in CsrfFilter::doFilterInternal method showing that the CSRF token is null

Fix the invalid CSRF token error

When inspecting the request in the developer console you’ll see the 403 error on mutable requests because the Headers section is missing the X-XSRF-TOKEN:

CSRF token not found gives the 403 Forbidden error

Avoid absolute urls

Angular HttpClient handles protection against Cross-Site Request Forgery attacks by default, as we can read in the documentation:

HttpClient supports a common mechanism used to prevent XSRF attacks. When performing HTTP requests, an interceptor reads a token from a cookie, by default XSRF-TOKEN, and sets it as an HTTP header, X-XSRF-TOKEN.

https://angular.io/guide/http#security-xsrf-protection

Nonetheless, we have to remember to avoid absolute paths when sending any mutable requests. The HttpXsrfInterceptor::intercept method is documented as this:

Skip both non-mutating requests and absolute URLs.
Non-mutating requests don’t require a token, and absolute URLs require special handling anyway as the cookie set on our origin is not the same as the token expected by another origin.

https://github.com/angular/angular/blob/ff9f4de4f1147ba9ea6d17c31442a2eedcf4e0d2/packages/common/http/src/xsrf.ts#L77

With that in mind, we can decide to use relative paths in our requests. Below you can find an example based on the TaskDataService class:

Configure proxy to a backend server

Now we need to divert all calls that use the /api path to a server, that in my example project, exposes endpoints on http://localhost:8080/api/*. In order to achieve that, we need to use the Angular proxy support. Create the following file in the src directory of your Angular project:

Next, I’m going to configure the $ ng serve command in my angular.json to use the proxy file:

Every time you update your proxy configuration rerun the $ ng serve command to make your changes effective.

Thanks to enabling the debug log level in my proxy.conf.json file I can read in my logs that the target was set properly:

Another key point is to read the Angular proxy documentation thoroughly in order to learn about:

To sum up, run the $ ng serve command and verify that the Angular app attaches the XSRF-TOKEN cookie and X-XSRF-TOKEN header to mutable requests as shown on the image below:

Both XSRF-TOKEN cookie and X-XSRF-Token header are included in my post request

Furthermore, you can find all the work that I described here in the scrum-ally and jwt-spring-boot-angular-scaffolding projects.

Learn more on debugging “Invalid CSRF token found” error

Photo by Mingyue H from Pexels

Leave a Reply

Your email address will not be published.