ValidateAntiForgeryTokenAttribute and Ajax Requests
Introduction:
Cross-Site Request Forgery (CSRF or XSRF) is still in the top ten list of The Open Web Application Security Project (OWASP). Fortunately, ASP.NET MVC has built-in support to mitigate this attack since its earlier versions. The default ASP.NET MVC template include code to mitigate this attack. But if you are using ajax requests then you need to keep some points in your mind. In this article, I will tell you some tips that will help you when you are doing CSRF protection in your ajax requests.
Description:
First tip is that when you send an ajax request to server then you need to explicitly attach anti-forgery token with your request. Let say you have this form in your ASP.NET MVC view,
@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { })) { @Html.AntiForgeryToken() ....................... .......................
Then you can easily include/attach the request anti-forgery token with your ajax request using these lines of javascript(assuming that you are using jQuery),
function appendAntiXsrfToken(data) { if (data instanceof Array) { data.push({ name: "__RequestVerificationToken", value: $('input[name=__RequestVerificationToken]').val() }); } else { data.__RequestVerificationToken = $('input[name=__RequestVerificationToken]').val(); } }; ................................................. appendAntiXsrfToken(data); $.ajax({ type: 'POST', url: uri, data: data, })
Note that I am appending anti-forgery token to data before sending ajax request. The data can be object or array. The function will automatically handle this.
On the server side, if you are using ajax then most of the time you need to send the anti-fogery exception type response in JSON format. You can handle this situation in a custom exception filter or in your BaseController.OnException method. Here is an example(you can change the JSON if you need different response),
protected override void OnException(ExceptionContext filterContext) { if (filterContext.ExceptionHandled || !Request.IsAjaxRequest() || !(filterContext.exception is HttpAntiForgeryException)) { base.OnException(filterContext); return; } filterContext.ExceptionHandled = true; filterContext.Result = new JsonResult { Data = new { code = 400, message = "Invalid Token" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; }
You can also put your controller action in try/catch block and invoke AntiForgery.Validate explicitly.
On the server side, if you are using ajax then most of the time you need to send the anti-fogery exception type response in JSON format. You can handle this situation in a custom exception filter or in your BaseController.OnException method. Here is an example(you can change the JSON if you need different response),
Summary:
Using ValidateAntiForgeryTokenAttribute with ajax requests, you might find some problems. In this article, I showed you some tips about using ASP.NET MVC ValidateAntiForgeryTokenAttribute with ajax requests.