i've stepped through my code a million times and can't find a problem with my implementation..
in custom AuthorizeAttribute i overwrote 2 methods
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (!httpContext.Request.IsAuthenticated)
return false;
var routeData = httpContext.Request.RequestContext.RouteData;
var ctrl = routeData.Values["controller"].ToString();
var action = routeData.Values["action"].ToString();
var user = httpContext.User.Identity.Name;
_logger.Info("[logging all the details]");
return ctrl == "SomeController";
}
protected override void HandleUnauthorizedRequest(AuthorizationContext ctx)
{
ctx.Result = new ViewResult { ViewName = "Unauthorized" };
// base.HandleUnauthorizedRequest(ctx);
}
the authorization logic is mocked to return false only on specific controller, and i've stepped through this to verify it's working correctly.
above code will cause infinite loop. in my log i can see that line hit 666 times (coincidence?) ..
if i do call base.HandleUnauthorizedRequest(ctx), all i get is a blank page. so i reflected what the base does, and it's this
filterContext.Result = new HttpUnauthorizedResult();
so this explains why it renders a blank page instead of redirecting to Unauthorized.cshtml. what i'm not sure about, is why does it go into an infinite loop if i don't call the base.
p.s.
i've verified that if i put the wrong Unauthorized view it will error out (but still hangs indefinitely)
System.InvalidOperationException: The view 'Unauthorized11' or its master was not found or no view engine supports the searched locations
Here is the implementation that i ended up going with and it's working very well.
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
// this is overriden for kendo menus to hide
var ctrl = filterContext.RequestContext.RouteData.GetRequiredString("controller");
var action = filterContext.ActionDescriptor.ActionName;
[custom authorization logic on action/ctrl]
// useful to determine if it's authorizing current controller path or menu links
var path = filterContext.HttpContext.Request.PhysicalPath;
_authorizingCurrentPath = path.Contains(ctrl) || path.EndsWith("WebUI") ;
if (userAuth < requiredAuth)
HandleUnauthorizedRequest(filterContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext ctx)
{
if (!ctx.HttpContext.User.Identity.IsAuthenticated)
base.HandleUnauthorizedRequest(ctx);
else {
if (_authorizingCurrentPath) {
// handle controller access
ctx.Result = new ViewResult { ViewName = "Unauthorized" };
ctx.HttpContext.Response.StatusCode = 403;
}
else {
// handle menu links
ctx.Result = new HttpUnauthorizedResult();
ctx.HttpContext.Response.StatusCode = 403;
}
}
}