Reputation: 6554
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
Global asax
protected void Application_Error()
{
System.Diagnostics.Debugger.Break();
}
IIS express throwing 401 unauthorised exception
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
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
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