Preventing CSRF attacks in JSON data posts with anti-forgery tokens in ASP.NET

Posted: (EET/GMT+2)

 

When you're sending JSON data to your ASP.NET (Core or classic MVC) backend, it's easy to forget that the usual form-based anti-forgery token protections do not automatically apply. CSRF attacks don't care whether you post form data or JSON payloads: they only care if they can get your browser to send a valid request.

Fortunately, you can still use anti-forgery tokens with JSON requests. The trick is to include the token yourself and send it through custom headers.

First, include the token in your Razor/CSHTML view (or even, the template layout):

@Html.AntiForgeryToken()

Then, pick up the token with JavaScript:

const token = document.querySelector("input[name='__RequestVerificationToken']").value;

When making your JSON call, send the token in a header:

fetch("/api/data", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "RequestVerificationToken": token
    },
    body: JSON.stringify({ message: "Hello" }) // your payload here
});

In your controller, require the anti-forgery token using the C# attribute:

[ValidateAntiForgeryToken]
public IActionResult Post([FromBody] MyData data)
{
  ...
}

Once everything is wired together, your JSON posts are protected just like normal form submissions. It's a small extra step, but well worth doing if your web API is part of a browser-based application.