Passing AntiForgeryToken to every POST request

The best practice is that all POST request has AntiForgeryToken to prevent XSS attack. If you don't know what it is, please, read materials in the bottom of the article. From MVC 3.5 there is a special attribute which can be applied to controller actions ValidateAntiForgeryTokenAttribute. It works in pair with HtmlHelper method Html.AntiForgeryToken(). The value of this token must be passed with every POST request to the action with the attribute.

The problem is how to make sure that it is passed regardless of what a developer does or does not. The ideal case when the developer does not bother about whether the forgery token is passed from a client to a server. The common case where this is real issue is using calls with . At the same time it is not a problem if you use AjaxHelper and posting forms, but it's still an issue for Ajax.ActionLink(). jQuery ajax calls can be done with $.ajax() and $.post(). The later is the wrapper for the former. In the ideal world the developer should make sure that forgery token is passed with calls of these methods. But in the real world the developer can forget about that, or you might developing a legacy code which must make sure that using is correct in all cases.In order to solve that we can rely on that fact the token always exists on the page and the later use jQuery ajax calls use that predefined information. It's not necessary to write one more wrapper for $.ajax(). You can just setup it when a web page is loaded.

You need the following JS code to do that:

function GetAntiForgeryToken() {
    var tokenField = $("input[type='hidden'][name$='RequestVerificationToken']");
    if (tokenField.length == 0) {
        return null;
    } else {
        return {
            name: tokenField[0].name,
            value: tokenField[0].value
        };
    }
}

$.ajaxPrefilter(
    function(options, localOptions, jqXHR) {
        if (options.type !== "GET") {
            var token = GetAntiForgeryToken();
            if (token !== null) {
                if (options.data.indexOf("X-Requested-With") === -1) {
                    options.data = "X-Requested-With=XMLHttpRequest" + ((options.data === "") ? "" : "&" + options.data);
                 }
                 options.data = options.data + "&" + token.name + '=' + token.value;
             }
         }
     }
 );
 

See Also

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Post

%d bloggers like this: