Friday, March 6, 2015

Every use of the Html.AntiForgeryToken helper injects a "X-Frame-Options: SAMEORIGIN" line into the header

We have recently encountered what I feel is a bug in the Html helper named AntiForgeryToken.  For every call to this helper, you will get one “X-Frame-Options: SAMEORIGIN” line stuck in your header.  

According to Microsoft guidance it should be used in conjunction with a form element.  The problem is that in MVC you can have as many forms on a page as you desire.  If you use the AntiForgeryToken helper with each one of them, you will get multiple instances of the “X-Frame-Options: SAMEORIGIN” line stuck in your header.  

I've recently encountered a page that had 147 instances of this line in the header and the page was being killed by default F5 router settings.  It was basically interpreting the excessive header lines as an injection attack of some form.  

If you encounter this, you have three options:
  • Increase the allowed header size in your routers and/or IIS.
  • Remove calls to Html.AntiForgeryToken helper (especially where forms are created in a loop). You will also have to remove the validation check on the controller side.
  • Add AntiForgeryConfig.SuppressXFrameOptionsHeader = true; to Global.ascx, which will remove X-Frame-Options: SAMEORIGIN” completely from your header.  
In my opinion, none of these are really good options.  I have also submitted a bug to Microsoft in the hopes that they will fix this problem.

A co-worker has suggested a possible solution (I have not tested it, but I will post it here) using a custom HtmlHelper:
public static MvcForm BeginAntiForgeryForm(this HtmlHelper htmlHelper)
{
            var mvcForm = htmlHelper.BeginForm();
            htmlHelper.ViewContext.Writer.Write(htmlHelper.AntiForgeryToken().ToHtmlString());
            //Remove X-Frame-Option header to remove duplicates
            HttpContext.Current.Response.Headers.Remove("X-Frame-Options");
            //Add it manually here or in IIS HTTP Response Headers
            HttpContext.Current.Response.Headers.Add("X-Frame-Options","SAMEORIGIN");
            return mvcForm;
}


References