ASP.NET Core MVC Testing And The Synchronizer Token Pattern

Have you ever try to call directly your ASP.NET MVC Post actions from your code (from a test method for instance)? If yes, according to your action configuration, you may had to deal with a Bad Request http status...
I had exactly the same problem when I wrote this post about ASP.NET Core MVC testing.

The Problem

This is a very standard behavior. Indeed, one of the most common security best practices in ASP.NET MVC is to protect your controllers from Cross Site Request Forgery (CSRF or Sea Surf) attacks.

This type of attack is intended to send request to a vulnerable site from a malicious one using the current logged user security information to access protected resources.

To preempt this kind of problem, one solution is to generate a token from the server that is sent back to the client (in ASP.NET, a hidden field is generated in the view which is returned to the client). Thus, when the client sends a request, the token has to be included within the content to be validated by the server, otherwise the request is aborted. To validate the token, the server must associate it with the user before returning it using a "user-session" mechanism or a cookie. The server then just compare the associated token with the one sent by the client. This pattern is called the Synchronizer Token Pattern.

The purpose of this post is not to make a deep dive into CSRF protection (see this link for more information about the ASP.NET implementation) but rather explain you how to deal with it within a test context with ASP.NET Core. Indeed, if you want to test your POST methods from an integration test or a behavior test with ASP.NET (see this post for further details about behavior testing), you have to figure out the Anti Forgery Token problem.

The Solution

To make the test successful, we have to simulate the Synchronizer Token Pattern with regard to ASP.NET implementation.

Workflow

Here is a solution workflow:1. Get the form view from the server and extract the token from the content2. Serialize the data we want to send to a url encoded string3. Send the POST request by injecting the token into the serialized data and the cookie collection.

Implementation

I have compiled the implementation as a single extension of the PostAsJsonAsync<> method: