Passing Anti-Forgery Token to MVC Actions using Ajax Post


 In this article I will show you a simple sample code base on how we can pass Anti-Forgery token to a MVC action through Ajax post calls. Entire sample is attached.

Client Side

1) Add Token to Layout page

Add following lines of code in the body section of …\Views\Shared\_Layout.cshtml page. 

 <script>
@functions{
public string GetAntiForgeryToken()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + "," + formToken;
}
}

</script>
<input type="hidden" id="forgeryToken" value="@GetAntiForgeryToken()" />

 

2) Add Token as Header to the Ajax Post method

Following lines of code are of interest

1) Read the forgery token  

var forgeryId = $(“#forgeryToken”).val();

 2)  Pass the forgery token as header to the Post method.

headers: {‘VerificationToken’: forgeryId }

 3)  Sample Ajax Request

 var forgeryId = $("#forgeryToken").val();
$.ajax({
url: 'HOME/POSTSAMPLEACTION',
type: "POST",
data: { name: "test" },
async: true,
dataType: "json",
headers: {
'VerificationToken': forgeryId
},
success: function (returnVal) {
alert(returnVal);
},
error: function (data) {
alert("failed");
},
});

 


Server Side

1) Add a custom filter or validating Ajax Requests for Anti-Forgery token.

We will write a custom validator attribute for validating Ajax Requests which need Anti-Forgery token to be set. Below is the code for the same. This primarily check the token value on the Ajax request and throws an exception if the token is not valid or not passed.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AjaxValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
try
{
if (filterContext.HttpContext.Request.IsAjaxRequest()) // if it is ajax request.
{
this.ValidateRequestHeader(filterContext.HttpContext.Request); // run the validation.
}
else
{
AntiForgery.Validate();
}
}
catch (HttpAntiForgeryException e)
{
throw new HttpAntiForgeryException("Anti forgery token not found");
}
}

private void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = string.Empty;
string formToken = string.Empty;
string tokenValue = request.Headers["VerificationToken"]; // read the header key and validate the tokens.
if (!string.IsNullOrEmpty(tokenValue))
{
string[] tokens = tokenValue.Split(',');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}

AntiForgery.Validate(cookieToken, formToken); // this validates the request token.
}
}

2) Assign the validator attribute to the Actions.

Add the validator attribute to the actions which need anti-forgery token for validation.

 [AjaxValidateAntiForgeryToken]
public JsonResult PostSampleAction(string name)
{
return this.Json("Post Passed Validation -" + name);
}

AntiForgerySample.zip

Comments (6)

  1. Sunny says:

    nice article !!!! Keep coming in more . Long way to go ……..

  2. Michael Bunney says:

    This is not a valid use of anti-forgery tokens.  You are storing both the form token and the cookie token in the form, delimited by a comma, and then comparing to see if they match.  All a hacker would have to do is set the token in his hidden format to "aaa,aaa" or any other pair of matching values, and this implementation would allow the request.

    The idea of anti-forgery tokens is that you store one in the form and one in an HTTP-only cookie of your site.  A malicious site can manipulate the form token of a forged request, but cannot manipulate the cookie that lives under your site's domain, so he can't make them match.  If you take both the form token and the cookie token from the form, the hacker can manipulate both of them to make them match.

  3. Rui Lima says:

    Michael is right. Don't use this approach.

  4. MP says:

    No guys, he is using AntiForgery.Validate. That is different than just matching the values. Try it.

    The whole reason for doing this custom work is because the default mechanism (submitting one through form post and the other through cookie) cannot work in AJAX (JSON) scenarios. Remember that an attacker cannot perform cross-domain AJAX calls and inject arbitrary headers (nor influence existing headers).

  5. Neil says:

    This is a very nice article. However, please careful since you are showing both tokens in the browser which can be reuse if the user is still logged in.

  6. sa says:

    I'm wondering..

    It's completely corresponds to MVC API ??