views:

497

answers:

1

After browsing the MVC section on CodePlex I noticed that the [Authorize] attribute in MVC returns a HttpUnauthorizedResult() when authorization fails (codeplex AuthorizeAttribute class).

In the source of HttpUnauthorizedResult() from CodePlex is the code (I'm not allowed to enter another URL as my rep isn't high enough, but replace the numbers on the URL above with 22929#266476):

// 401 is the HTTP status code for unauthorized access - setting this
// will cause the active authentication module to execute its default
// unauthorized handler
context.HttpContext.Response.StatusCode = 401;

In particular, the comment describes the authentication module's default unauthorized handler.

I can't seem to find any information on this default unauthorized handler. In particular, I'm not using FormsAuthentication and when authorization fails I get an ugly IIS 401 error page.

Does anyone know about this default unauthorized handler, and in particular how FormsAuthentication hooks itself in to override it?

I'm writing a really simple app for my football team who confirm or deny whether they can play a particular match. If I enable FormsAuthentication in the web.config the redirect works, but I'm not using FormsAuthentication and I'd like to know if there's a workaround.

+1  A: 

If you have Reflector, take a look at System.Web.Security.FormsAuthenticationModule.Init(). This method hooks Application_EndRequest and calls OnLeave(). The OnLeave() method checks that the response code is HTTP 401. If it is, then the module performs a redirect rather than bubbling the 401 up to the client. (This logic is what the comment is referring to as the 'default unauthorized handler.') In your particular case, ASP.NET is letting the 401 bubble up to the client, but IIS is intercepting it and displaying an ugly error page.

You can do something very similar from within Global.asax. Make a method Application_EndRequest; this method will be called at the end of every request serviced by your application. From here, you can do whatever you want. If you want to check if the response is a 401 and redirect them to a different page, you can do so from here.

Levi
Thanks Levi - I haven't really used Reflector but will take a look at it. I should have suspected it might have been something hooking into the EndRequest event, although it seems quite an unglamarous way of doing the redirect. I guess the other option would be to create a custom authorization class, which when authorization fails calls a different method to HttpUnauthorizedResult() which could return a different ActionResult (which could be the authorization failure info page)?
Anthony
That would work. If you go this route, subclass AuthorizeAttribute and override the HandleUnauthorizedRequest() method. The only real benefit to hooking EndRequest over this is that hooking EndRequest allows you to trap authorization failures from other parts of the app, not just [Authorize].
Levi
I think hooking EndRequest sounds like a better use of time because, like you say, could cover more of the app. I've also read about the AuthorizeAttribute and potential problems with output caching - there's even a comment about it in the codeplex source, although actually if I've got the time I guess it wouldn't hurt to do both types of authorization. Although I'll start with the EndRequest. Thanks for your help Levi.
Anthony