In this blog post, I want to share a small piece of ASP.NET Core middleware that implements antiforgery token validation for all POST requests.
If you're not yet familiar with cross-site request forgery (CSRF/XSRF) or antiforgery tokens as a defense mechanism, I recommend you read the following articles first:
Before we take a look at the middleware itself, let's recap how we can secure each ASP.NET MVC controller action manually, one by one.
Update (June 12, 2017): In the meantime, Andrew Lock has blogged about using the built-in
[AutoValidateAntiforgeryTokenAttribute] for validating all requests. Make sure to check out his post as well!
The Manual Approach
To secure a controller action against CSRF, we can decorate it with the
[ValidateAntiForgeryToken] attribute. The action will then only execute if the HTTP request contains a valid antiforgery token:
public ActionResult Logout()
Within our Razor views, we can use the
@Html.AntiForgeryToken() method to have the framework generate a hidden
<input> holding the expected antiforgery token:
<form action="..." method="POST">
<!-- ... -->
This approach works, but it has a drawback: We have to manually decorate every controller action that deals with POST requests with the
[ValidateAntiForgeryToken] attribute, which is a little cumbersome. More importantly, though, it's quite easy to forget to add the attribute, which makes the corresponding controller action vulnerable to CSRF attacks.
Let's see how we can implement the antiforgery token validation in a single place so that it "just works" for all POST requests.
Using Middleware to Validate Antiforgery Tokens
Here's the middleware in its entirety:
public class ValidateAntiForgeryTokenMiddleware
private readonly RequestDelegate _next;
private readonly IAntiforgery _antiforgery;
public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery)
_next = next;
_antiforgery = antiforgery;
public async Task Invoke(HttpContext context)
The idea is that we check whether the current HTTP request is a POST request, and if it is, we validate that it was sent with a correct antiforgery token. This validation functionality is provided by the
IAntiforgery service, which we resolve via the constructor of the middleware.
If the request does not contain a valid antiforgery token, the
ValidateRequestAsync method will throw an
AntiforgeryValidationException. In this case,
_next(context) will not be called and the rest of the request pipeline won't be executed. It is then up to some error handling middleware to display an error to the user.
Adding Our Middleware to the Request Pipeline
Of course, simply creating the middleware class is not enough. We have to instantiate it and add it to the request pipeline to take effect:
public void Configure(IApplicationBuilder app)
Here, I've written a simple extension method that follows the
Use... naming scheme which is common in ASP.NET Core:
public static class ApplicationBuilderExtensions
public static IApplicationBuilder UseAntiforgeryTokens(this IApplicationBuilder app)
And there we go! We now automatically validate antiforgery tokens for each POST request.