Implementing AntiForgery Token in AJAXPOST






4.18/5 (6 votes)
This is to implement anti forgery token with Ajax post in MVC Application
Table of Contents
- Introduction
- Steps to implementing Antiforgery token through AJAXPOST in MVC [Razor]
- Control Flow
Introduction
Antiforgery token is required where we need to implement CSRF [Cross-Site Request Forgery]. It is a simple trick. In Master page, Get the Token by using server code and store it as global JSON object with property name ‘RequestVerificationToken
’, bind the token to the header of the Ajax post. In server side, create a filter that gets the token by property name ‘RequestVerificationToken
’ and validate. Follow the below steps for better understanding.
Steps to Implementing Antiforgery Token Through AJAXPOST in MVC [Razor]
Step 1: Get Token Value in Master Page Through Server Code
@{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
var tokenHeaderValue = cookieToken + ":" + formToken;
}
cookieToken
: token stored inside the cookieformToken
: token sent to your page for the formsAntiForgery.GetTokens();
stores the token value inside the variable ‘cookieToken, formToken
’
Add the above code in your Master page or the page where you require antiforgery token.
Step 2: Assign the Token Value as Global Variable in JQuery
<script type="text/javascript">
var TOKENHEADERVALUE = '@tokenHeaderValue';
</script>
Store ‘@tokenHeaderValue
’ in the Global JQuery variable ‘TOKENHEADERVALUE
’.
Place the above code in page where you placed Step 1 code.
Step 3: Setup the Ajax with Header
$(document).ready(function () {
$.ajaxSetup({
headers: {
'RequestVerificationToken': TOKENHEADERVALUE
},
});
});
Inside $.ajaxSetup({…. });
, place the headers object with property ‘RequestVerificationToken
’ contains the token value from the Global variable ‘TOKENHEADERVALUE
’.
$.ajax({
url: url,// URL to the Action method
type: 'POST',//Type 'GET'/ 'POST'
contentType: 'application/json;charset=utf-8', // Content Type
data: dataObj,// Data to be sent as parameter
success: function (data) {alert('Success!');}, //Return to success property after
//successful return from the action method
error: function(data) { alert('Error!');} //Return to error when there any error in Ajax call
});
This ‘$.ajaxSetup({…. });
‘ adds the ‘headers’ as one more property to the above $.ajax
call. Whenever the there is an Ajax call within the scope where ‘$.ajaxSetup({…. });
‘ is specified, [i.e., if ajaxsetup
is specified globally to the entire application, then it binds headers
property to all Ajax calls throughout the application].
Step 4: Create a Custom Validation Filter
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ValidateCustomAntiForgeryTokenAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//throw new NotImplementedException();
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext != null && filterContext.HttpContext != null &&
filterContext.HttpContext.Request != null &&
!string.IsNullOrEmpty(filterContext.HttpContext.Request.HttpMethod)
&& string.Compare(filterContext.HttpContext.Request.HttpMethod, "POST", true) == 0)
{
ValidateRequestHeader(filterContext.HttpContext.Request);
}
}
private void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = "";
string formToken = "";
IEnumerable<string> tokenHeaders = request.Headers.GetValues("RequestVerificationToken");
if (tokenHeaders != null && tokenHeaders.Count() > 0)
{
string[] tokens = tokenHeaders.First().Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
}
}
}
Create ValidateCustomAntiForgeryTokenAttribute
filter and register in FilterConfig
as filters.Add(new ValidateCustomAntiForgeryTokenAttribute());
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new ValidateCustomAntiForgeryTokenAttribute());
}
}
This class is available inside App_Start folder in the MVC Project.
Step 5: Assign Filter to the Action Method Called in Ajax Post
[HttpPost]
[ValidateCustomAntiForgeryToken]
public JsonResult IndexSingle(string data)
{
return Json(data, JsonRequestBehavior.AllowGet);
}
Here, the filter checks before the control hits the action and validates the token proceed if token is valid, otherwise control will not go to the corresponding method.
Control Flow
- Request from the Ajax call
$.ajax({});
- Hits the filter if it is a valid Ajax call.
Control goes to:
public void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext != null && filterContext.HttpContext != null && filterContext.HttpContext.Request != null && !string.IsNullOrEmpty(filterContext.HttpContext.Request.HttpMethod) && string.Compare(filterContext.HttpContext.Request.HttpMethod, "POST", true) == 0) { ValidateRequestHeader(filterContext.HttpContext.Request); } }
- In
If()
condition, it checks the request to the server is Ajax post request or not if the condition istrue
, then it callsValidateRequestHeader(filterConte…….);
method with the request as parameter.private void ValidateRequestHeader(HttpRequestBase request) { string cookieToken = ""; string formToken = ""; IEnumerable<string> tokenHeaders = request.Headers.GetValues("RequestVerificationToken"); if (tokenHeaders != null && tokenHeaders.Count() > 0) { string[] tokens = tokenHeaders.First().Split(':'); if (tokens.Length == 2) { cookieToken = tokens[0].Trim(); formToken = tokens[1].Trim(); } System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken); } }
- In this method, it separates the token from the headers with property name
["RequestVerificationToken"]
specified in the$.ajaxSetup({})
. - Split the token value to get the
cookieToken
andformToken
which is separated by ‘:
’ - Validate the token as
System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
If valid, the control proceeds to the action method called through $.ajax
.