Phil Murray
Phil Murray

Reputation: 6554

Capture exceptions from Authorize attribute in MVC4

I have the added the Authorise attribute in my MVC4 application using Windows Authentication and while testing I changed the name of the active directory group to check that the Application_Error method in the Global.asax class would capture a non authorised user.

The problem is that the exception is not captured and IIS express throws a 401 exception. Can these type of authorisation exception be caught, if so are there better ways to handle exceptions in MVC application?

Method

enter image description here

Global asax

protected void Application_Error()
{
    System.Diagnostics.Debugger.Break();
}

IIS express throwing 401 unauthorised exception

enter image description here

Working validation

Using this method works but its a little messy.

if (User.IsInRole(@"DOMAIN\USER"))
{
    if (ModelState.IsValid)
    {
        ctx.SaveChanges(model);
        ViewBag.Notification = "Save Successful";
    }
}
else
{
    throw new HttpException(404, "Category not found");
}

Upvotes: 2

Views: 5634

Answers (2)

Phil Murray
Phil Murray

Reputation: 6554

After further research I found a couple of blog posts from Michael Mckenna in Part1 and Part2 he details his exception handling strategy which I have got to work by manually testing is a user is in an active directory group and if not throwing an HTTPException.

This gets around the issue but still does not capture any exceptions when using the AuthorizeAttribute

Global.asax

 protected void Application_Error()
    {
        var exception = Server.GetLastError();
        Server.ClearError();
        var httpException = exception as HttpException;

        //Logging goes here

        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";
        routeData.Values["action"] = "Index";

        if (httpException != null)
        {
            switch(httpException.GetHttpCode())
            {
                case 401:
                    routeData.Values["action"] = "NotAuthorised";
                    break;
                case 402:
                case 403:
                    routeData.Values["action"] = "NotAuthorised";
                    break;
                case 404:
                    routeData.Values["action"] = "NotFound";
                    break;
            }

            Response.StatusCode = httpException.GetHttpCode();
        }
        else
        {
            Response.StatusCode = 500;
        }

        // Avoid IIS7 getting involved
        Response.TrySkipIisCustomErrors = true;

        // Execute the error controller
        IController errorsController = new Jmp.StaticMeasures.Controllers.ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new RequestContext(wrapper, routeData);
        errorsController.Execute(rc);
    }

Error Controller

using System.Web.Mvc;

    namespace Jmp.StaticMeasures.Controllers
    {
        public class ErrorController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }

            public ActionResult NotFound()
            {
                return View();
            }

            public ActionResult NotAuthorised()
            {
                return View();
            }

        }
    }

Upvotes: 3

artokai
artokai

Reputation: 405

I don't think that AuthorizeAttribute throws any exceptions when it encounters an unauthorized request. It just sends the 401 response to the client.

If you want something else to happen, you can inherit from the AuthorizeAttribute class and override the HandleUnauthorizedRequest-method. If you want an exception to be thrown, you can throw it from there.

public class ThrowingAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        throw new HttpException(401, "Unauthorized");
    }
}

Here's a link to the AuthorizeAttribute sourcecode, so you can check what it does:

Upvotes: 1

Related Questions