First of all, since my last post indicated I would be gone a while because of Huricane Ike, I guess it wouldn't hurt to provide an update. Well, I still have a little bit of work to do on the house, but things are mostly back to normal for me. There are still a lot of people in the Houston area recovering from the storm. I've personally helped clean up two homes that had water 4-5 feet high on the first floor. This makes me all the more glad that I am on the north side away from the storm surge.
Anyway, I thought I would just jump right back in the saddle with something that I've found lots of people asking about but only a few solutions. All of the solutions I have found (including my own adapted solution) are specific to a particular ASP.Net configuration. The problem:
Redirect a user to an Unauthorized page when they attempt to navigate to a page they have no access to. There are many nuances to this problem. It really all depends on your ASP.Net configuration. Are you using Windows authentication? Forms Authentication? Are you using membership and role providers?
My specific situation is an ASP.Net web site that uses both Membership and Role providers, in addition to Forms authentication. The crux of the problem is that ASP.Net is too smart for it's own good. When you set up Forms authentication in the web.config, one of the attributes includes the loginUrl. This is used, firstly, for identifying the login page when the user is not yet authenticated.
When you throw authorization into the mix, the loginUrl is used yet again. The FormsAuthenticationModule intercepts any 401 (not authorized) sent by the UrlAuthorizationModule and translates it into a 302 (redirect), redirecting to the login page. I'm not quite sure why it was designed this way. Clearly based on all of the posts on the net, there is a high demand for different behavior (that is, a separate "unauthorized" page). The solution:
After playing with various solutions, I finally adapted a few of them into something I am comfortable with. Granted, this is proprietary to ASP.Net's current behavior and may require changing in the future. Hopefully, when a change is required, it will mean that Microsoft has provided a better solution (perhaps another web config attribute for the unauthorized page, or honoring the customErrors configuration).
Regardless, my solution involves intercepting the EndRequest event on the Application instance:
1 void Application_EndRequest( object sender, EventArgs e )
3 if(User.Identity.IsAuthenticated && Response.StatusCode == 302 && Response.RedirectLocation.ToUpper().Contains( "LOGIN.ASPX" ))
5 if(!UrlAuthorizationModule.CheckUrlAccessForPrincipal( Request.FilePath, User, "GET" ))
7 Response.RedirectLocation = "/Unauthorized.aspx";
Basically, I check to see if the response is a redirect to the login page and if the user has already been authenticated. Finally, I check to see if the user does not have access from the original requested page. If all of those conditions are true, then I redirect them to the unauthorized page, instead of the login page.
Anyway, I hope this helps someone. Now at least I won't have to search too long the next time I need it.