ASP.NET Core - Validate Antiforgery token in Ajax POST How to issue a proper Ajax POST request using jQuery or other JavaScript frameworks in an ASP.NET Core application with the Antiforgery Middleware and AntiForgeryToken enabled

How to fix the "No executable found matching command dotnet-ef" error in Visual Studio with .NET Core

If you've stumbled upon this article it most likely means that you're looking for a way to validate your ASP.NET Core Antiforgery Token when issuing an Ajax POST using jQuery or other JavaScript frameworks without getting the following HTTP Status Code error:

405 Method Not Allowed

If this error is preventing you from performing your Ajax POST requests to your controllers or Razor Pages, don't worry: you found the right place to fix your issue for good.

However, before releasing the fix, let's spend a couple minutes to recap how the Antiforgery token works in the context of ASP.NET Core Data Protection and why is important to learn how to properly deal with it instead of turning it off spamming the [IgnoreAntiforgeryToken] attribute in all of our Controllers that responds to AJAX or REST-based calls.

What is Antiforgery and why is it so important?

The purpose of anti-forgery tokens is to prevent cross-site request forgery (CSRF) attacks. The technique consists into submitting multiple different values to the server on any given HTTP POST request, both of which must exist to make the server accept the request: one of those values is submitted as a cookie and another one in the request's HTTP headers OR in a Form input data. If those values (tokens) don't exist or don't match, the request is denied with a 405 Method Not Allowed Status Code.

Now, while the cookie token is handled automatically by the browser, the form input data token has to be generated within the form: in most frameworks, this is often a task that the developers must implement on they own, as well as the server-side token verification task; luckily enough, the ASP.NET Core framework automatically handles such task thanks to the Antiforgery built-in Middleware.

How the ASP.NET Core AntiForgery works

As you probably already knows, ASP.NET Core implements antiforgery through a dedicated middleware tat gets added to the Dependency injection container when one of the following APIs is called in the ConfigureServices() method of the project's Startup.cs file:

  • AddMvc
  • MapRazorPages
  • MapControllerRoute
  • MapBlazorHub

Once added, the Antiforgery token is automatically appended to each and every HTML <form> element in all Razor Pages and Views in the form of a <input type="hidden"> HTML field similar to the following:

More precisely, the automatic generation of antiforgery tokens in <form> HTML elements takes place when the following conditions are met:

  • the <form> tag contains the method="post" attribute;
  • the action attribute is empty (action="") or not present;

When this element is generated and appended to the HTML Form, it gets POSTed to the back-end together with the ViewModel (or raw) form data: the back-end will then automatically validate it and accept or deny the request (with the 405 Method Not Allowed HTTP Error) depending on the validation result. The best part of the whole story is that we don't need to do anything, before all of these tasks are automatically handled by the framework in a seamless way.

This means that we can create this form in a Razor View:

Which will be rendered in the following way:

And then validated by the Controller that will automatically before accepting the request and executing the corresponding Action Method's code:

As we can see, the developer doesn't need to do anything... not even the [ValidateAntiForgeryToken] and/or [AutoValidateAntiforgeryToken] attribute filters just like it was back in the day with ASP.NET Framework 4.x: the whole process is now enabled and active by default; in case we want to opt-out from the validation process and accept any requests, we can do that by decorating our Controllers (and/or Action Methods) with the [IgnoreAntiforgeryToken] attribute filter. However, doing that will leave that method exposed to CSRF-based attacks, thus weakening our web application.

Why we would ever want to do that?

If you managed to follow the story so far, you've probably already figured

The issue

If you managed to follow the story so far, you've probably already figured out where the problem actually lies: as we explained early on, the Antiforgery process is made up of two distinct actors that take place in two different moments within the HTTP request lifecycle:

  • the form <input type="hidden"> tag, originated on the client-side and POSTed together with the form data and cookies;
  • the verification process of such tokens, handled on the server-side by the Controller where the request is routed to;

Now, when the client-side form is generated within Razor Pages or Views, we've seen how everything will reasonably work in a seamless way because the input tag will be generated automatically; however, that's not the case when we issue AJAX Post requests using vanilla JavaScript or a JS framework such as jQuery.

To put it in other words, if we do something like this in our Razor Page of View:

The antiforgery token won't be automatically generated, as ASP.NET Core doesn't know that syntax and won't be able to append anything to it.

What happens when that POST request hits the Action Method without the Antiforgery token? We already know that: the 405 Method Not Allowed HTTP Error.

The solution

In order to fix such issue, we have 2 options:

  • add the [IgnoreAntiforgeryToken] attribute filter to our Controller's method;
  • find a decent way to append the Antiforgery token to the Ajax request;

It goes without saying that the former option is highly discouraged, for a number of security considerations which we've already talked about early on: let's see how we can implement the latter.

#1. Looking around

The first thing to do is to go see how the Antiforgery system is configured in our web application.

Such info is usually present in the ConfigureServices() method of our app's Startup.cs file, where we should be able to find something like this:

If the service is configured in the following way, it means that the default values will be used: when this kind of scenario occurs, the <input type="hidden" /> that gets automatically appended to each Razor Page or View form has a name equals to __RequestVerificationToken.

However, most Visual Studio and Visual Studio Code templates uses a slightly different approach that includes some minimal level of personalization in the Cookie, Header and Form field names:

If our web application features something like this, it goes without saying that the <input type="hidden" /> will have a name attribute equals to X-CSFR-TOKEN-OurAppName.

Now that we know the input name, we know the first half of our answer: we definitely need to add a new key to our Ajax POST data object equals with the same name we've just discovered. However, we're still missing the most important part: a valid Antiforgery token value.

#2. Inject the IAntiforgery interface

The only way to retrieve a valid Antiforgery token is to have the Antiforgery system to generate one. In order to do that we need to find a way to access to that service from our Razor Pages or Views.

Luckily enough, we can inject it using the Dependency Injection pattern by adding the following code to the top of our Razor Page/View:

This will allow us to use the Antiforgery interface from within our Page/View in the following way:

The tokenSet variable will be an instance of the AntiforgeryTokenSet class, which hosts an antiforgery token pair (cookie and request token) for a request. Once retrieved such object, we can do this:

As we can see, we didn't even use the form's input field name that we discovered a few while ago: we'll just fetch it from the tokenSet object together with the token value itself, so that our code will work even if we'll change that in the future.

Alternatively, if you prefer to send the Antiforgery token in the request's HTTP headers, you might want to use the following approach:

With any of these neat add-ons, our Ajax POST request will be accepted by the Controller: no more 405 Method Not Allowed errors for us!

Conclusion

That's it, at least for the time being: I hope that this post will help other ASP.NET Core developers that are looking for a way to overcome the 405 Method Not Allowed HTTP error when trying to perform Ajax POST requests within a ASP.NET Core web application that does implement the Antiforgery system.

If you want to know more about .NET Core and Angular check out the ASP.NET Core 5 and Angular book, available as paperback and e-book.

 

About Ryan

IT Project Manager, Web Interface Architect and Lead Developer for many high-traffic web sites & services hosted in Italy and Europe. Since 2010 it's also a lead designer for many App and games for Android, iOS and Windows Phone mobile devices for a number of italian companies. Microsoft MVP for Development Technologies since 2018.

View all posts by Ryan

One Comment on “ASP.NET Core - Validate Antiforgery token in Ajax POST How to issue a proper Ajax POST request using jQuery or other JavaScript frameworks in an ASP.NET Core application with the Antiforgery Middleware and AntiForgeryToken enabled

  1. Where is Context defined for the following statement:

    var tokenSet = antiforgery.GetAndStoreTokens(Context);

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.