Custom ASP.NET MVC Authorization Attribute For Ajax Requests

by Bill Beckelman 1. April 2010 14:34

One issue that I have had for a while that I think I finally solved was what to do with unauthorized jQuery Ajax requests in my ASP.NET MVC application. I finally wrote a custom authorization attribute to take care of the situation.

I ran into two issues while constructing the attribute; the first was the need to send back different responses depending upon the content type of the request. The second was that the ASP.NET framework intercepts 401’s no matter what you do with your web config. You can see in the code below how I addressed these two issues.

 

Code Snippet
  1. public class CustomAuthorizeAttribute : AuthorizeAttribute
  2. {
  3.     public override void OnAuthorization(AuthorizationContext filterContext)
  4.     {
  5.         base.OnAuthorization(filterContext);
  6.         if (filterContext.Result == null || (filterContext.Result.GetType() != typeof(HttpUnauthorizedResult)
  7.             || !filterContext.HttpContext.Request.IsAjaxRequest()))
  8.             return;
  9.  
  10.         var redirectToUrl = "/login?returnUrl=" + filterContext.HttpContext.Request.UrlReferrer.PathAndQuery;
  11.  
  12.         filterContext.Result = filterContext.HttpContext.Request.ContentType == "application/json"
  13.             ? (ActionResult)
  14.               new JsonResult
  15.               {
  16.                   Data = new { RedirectTo = redirectToUrl },
  17.                   ContentEncoding = System.Text.Encoding.UTF8,
  18.                   JsonRequestBehavior = JsonRequestBehavior.DenyGet
  19.               }
  20.             : new ContentResult
  21.             {
  22.                 Content = redirectToUrl,
  23.                 ContentEncoding = System.Text.Encoding.UTF8,
  24.                 ContentType = "text/html"
  25.             };
  26.  
  27.         //Important: Cannot set 401 as asp.net intercepts and returns login page
  28.         //so instead set 530 User access denied            
  29.         filterContext.HttpContext.Response.StatusCode = 530; //User Access Denied
  30.         filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;            
  31.     }
  32. }

Note: The idea to send a different status code is from a comment that Craig Stuntz made on this Stackoverflow post.

Then on the client side, my default jQuery Ajax setup has a check in the error handling to look for the 530 status code and if found it resets the window’s location as needed.

What would you do different or what did I not think of?


About Me

I live and work in Salt Lake City, Utah. My background is in aviation. I have a degree in Aeronautical Science from Embry-Riddle Aeronautical University in Prescott, AZ. I have worked as a commercial airline pilot and most recently as a technical advisor for a charter airline.