MVC Custom errors, HTTP status codes and SecurityException

We use Windows Identity Foundation in my current project. WIF introduced the Claim based authorization in .NET 4.5 which is a welcomed addition since we were forced to use outdated tools like EnterpriseLibraries Rule authorization to achieve something similar before it.

Whenever a claim is not met WIF will throw a System.Security.SecurityException exception which will not play nicely with MVC Custom errors because it will render a status 500 instead of the correct status 403. This is not very user friendly since the user will think something is wrong instead of understanding that he or she needs to order additional privileges to access said part of the system.

The solution is really simple and I did not find it when googling, thus this blog post 😀

Most solutions I found implemented the MVC Authorize attribute, this means that you will have to replace all Claim attributes that you are already using, plus it means that SecurityExceptions that are thrown in layers below the Web layer will still be treated as 500’s. The better solution is to create a custom HandleErrorAttribute. The HandleErrorAttribute is a global filter that will trigger whenever a exception is thrown.

public class HandleClaimsErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);
        if (filterContext.Exception is SecurityException)            
            filterContext.HttpContext.Response.StatusCode = 403;
    }
}

We trigger the default behavior through the base class and then we look to see if the exception is a SecurityException. This code is a bit naive since it assumes that all SecurityExceptions are 403 (Unauthorized).

You need to replace the default filter with our custom one, if you use vanilla MVC you do it from the FilterConfig class like

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleClaimsErrorAttribute());
        }
    }

If you are using a Dependency injection framework like Ninject the process can be different.

Now your custom error page can present the real error to the user. Note that this will only work for MVC controllers, so it will not apply to WebAPI controllers, this needs to be addressed to get 403 from ajax requests etc, will update blog when that is fixed.

Advertisements

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