ASP.NET Core Pitfalls – AJAX Requests and XSRF

When using Anti Cross Site Scripting Forgery (XSRF) protection in your application, which is on by default, you may be surprised when you try to AJAX submit to a controller and you get a HTTP 400 Bad Request: this may be happening because the framework is blocking your request due to XSRF.

Imagine this scenario: you have a global AutoValidateAntiforgeryTokenAttribute or ValidateAntiForgeryTokenAttribute filter applied to your site, controller, or action method:

services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

In this case, the framework is expecting a header field with a name of “RequestVerificationToken” (this is the default, but can be configured) with a valid token value. If does not receive it, or receives an invalid value, then it returns HTTP 400.

You can sort this out by adding the header manually to the AJAX request. If using jQuery, you have at least two options, using ajaxSetup or ajax. Let’s see an example using ajax:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf

<script>

function sendRequest() {

$.ajax({
      url: '/Home/Process',
         headers: {
          '@Xsrf.GetAndStoreTokens(Context).HeaderName': '@Xsrf.GetAndStoreTokens(Context).RequestToken'
         },
         data: { },
         type: 'POST',
         success: function (data) {
         },
         complete: function () {
         },
         error: function (error) {
         }
     });
}

</script>

This code should go in a .cshtml file. As you can see, I am injecting an IAntiforgery instance, this is registered automatically by ASP.NET Core. The header that I am sending is whatever is configured, and can be changed in ConfigureServices:

services.AddAntiforgery(options =>
{
options.HeaderName = "x-header-name";
});

Another option, of course, is to add an IgnoreAntiforgeryTokenAttribute to the controller action method for which you do not want the validation to occur:

[HttpPost]
[IgnoreAntiforgeryToken]
public IActionResult Process()
{
//do something
return Json(true);
}

Any way, this will allow the code to execute.

As always, hope you find this useful!

                             

1 Comment

Add a Comment

As it will appear on the website

Not displayed

Your website