Monday, April 9, 2012

Ajax call and Antiforgery Token

Asp.Net Mvc has antiforgery tokens to inject some random token to your html and verify that from server. That is great for regular pages, but I dont like it for ajax post actions to render partial data.

You can create your custom Authorize attribute with additional property to skip forgery check for specific methods.

Custom attribute code:


   [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeForgeryCheck : AuthorizeAttribute
    {
         /// <summary>
         /// Dont check antiforgery token
         /// </summary>
        public bool ExcludeAntiForgery { get; set; }
        public override void OnAuthorization(AuthorizationContext filterContext)
         {
             //We will check anti-forgery  for  Post action, but exclude if attribute says exclude
             if (String.Compare(filterContext.HttpContext.Request.HttpMethod, "post", true) == 0)
             {
                 var authorize = new AuthorizeAttribute();
                 authorize.OnAuthorization(filterContext);
                 if (filterContext.Result != null) // Short circuit validation
                     return;
                 if (!ExcludeAntiForgery)
                 {
                     var forgery = new ValidateAntiForgeryTokenAttribute();
                     forgery.OnAuthorization(filterContext);
                 }
             }
             base.OnAuthorization(filterContext);
        }
    }


Sample partial method in a controller with this attribute. We are still checking authorization,but skipping antiforgery token. You can also have this attribute at class level. Method level will override that.


 /// <summary>
        /// show job history from ajax call
        /// </summary>
        /// <returns></returns>
        [HttpPost][AuthorizeForgeryCheck(ExcludeAntiForgery = true)]
        public ActionResult JobHistory(int id)
        {
            var historyrecords = db.MailJobHistories.Where(a => a.MailJobId == id).OrderByDescending(a => a.ModifiedOn);

            return PartialView(historyrecords.ToList());


        }

You can call this method from Ajax post without forgery token. It will still check if user is authorized.

No comments:

Post a Comment

Hey!
Let me know what you think?