Adding ASP.NET MVC Anti-Forgery Tokens To All Post Requests Easily

One of the newer attacks against web applications is the cross-site request forgery attack. It’s an attack against modern applications that store a cookie to represent the currently logged in user. The problem has been explained in other web sites. I’d highly recommend checking out Phil Haack’s blog post on the subject.

One of the techniques to prevent this attack is to add an anti-forgery token using the @Html.AntiForgeryToken extension method. On the controller side, the action method defines the [ValidateAntiForgeryToken] attribute. Behind the scenes, the hidden input field for the anti-forgery token is validated by the MVC framework to ensure it’s correct. This has also been explained well; see Steve Sanderson’s post on the subject. While there is discussion as to whether this approach is needed just for the logging in an anonymous posts, or all posts in general, as been up for debate. But the point of CSRF is to attack authenticated users.

I’m not real fond of repetitive coding, especially when the framework is flexible enough to avoid it. Below is my solution to to create a flexible solution to validate all post operations. The first task is to create an attribute for validating the token. After using .NET Reflector by Red Gate to examine the existing ValidateAntiForgeryTokenAttribute class, the token is simply an authorization attribute that validates the request using a helper utility to validate it. See the example below.

public class GlobalAntiForgeryTokenAttribute
  : FilterAttribute, IAuthorizationFilter
{
  public sub OnAuthorization(filterContext As AuthorizationContext)
  {
	if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST")
	{
	  AntiForgery.Validate();
    }	
  }
}

Make sure to add this to the GlobalFilters.Filters collection:

GlobalFilters.Filters.add(new GlobalAntiForgeryTokenAttribute);

On authorization of the request, if the operation is a POST request, we call the Validate() method on the AntiForgery helper to actually perform the validation. All of our post operations are now checked for forgery; however, this will fail because we haven’t added our token globally. To do that, we have to create a custom form extension method like the following:

public static void FormExtensions
{
   public static MvcForm BeginDataForm(this HtmlHelper html, string action, string controller, ...)
   {
     var form = html.BeginForm(action, controller, ...);
	 //At this point, the form markup is rendered in BeginForm
	 // we can render the token
	
	 //With every form, we render a token, since this
	 //assumes all forms are posts
	 html.ViewContext.Writer.Write(html.AntiForgeryToken().ToHtmlString());
	
	return form;
   }
}

If we use our custom helper for all of our forms, then all of our custom forms will have rendered an anti-forgery token. Therefore we don’t have to worry about creating it ourselves, saving time and reducing code.

Advertisements

2 thoughts on “Adding ASP.NET MVC Anti-Forgery Tokens To All Post Requests Easily

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s