Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Customizing the Authorize attribute

, 15 Apr 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Extending the built-in Authorize attribute.

"THE ARTICLE IS NO LONGER MAINTAINED HERE. PLEASE POST ANY FURTHER DISCUSSIONS/QUESTIONS IN MY BLOG http://www.prideparrot.com/blog/archive/2012/6/customizing_authorize_attribute" - Author

Authorize

The Authorize attribute available in MVC framework helps to restrict users from accessing secured controllers and actions. When a user who is not authenticated or authorized tries to access the controller or action that is decorated with Authorize attribute generates a 401 response and if the site has forms authentication enabled then the user will be directed to the login page. The problem with this behavior is the authenticated user (but not authorized) also get directed to the login page, mostly developers like to show an access denied page in those case.

This article is mostly a kind of tip that describes how we can achieve that by extending the built-in Authorize attribute.

HandleUnauthorizedRequest

The Authorize attribute implements IAuthorizationFilter and exposes a bunch of virtual methods (AuthorizeCore, HandleUnauthorizedRequest, OnAuthorization, OnCacheAuthorization) that we can override. OnAuthorization method is the main that calls the other virtual methods, it calls the AuthorizeCore to know whether the user is authenticated and authorized to access the controller or action. The method returns false if the authorization fails and is it is then the OnAuthorization calls the HandleUnAuthorizeRequest to take appropriate action.

The advantage of splitting the complete authorization process into pieces of function is we can override only the ones required and reusing the others else we have to do the complete implementation. The default implementation of HandleUnAuthorizeRequest is it returns 401.

This is the HandleUnAuthorizeRequest code that I copied from CodePlex.

protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
    filterContext.Result = new HttpUnauthorizedResult();
}
Listing 1. HandleUnauthorizedRequest default implementation

It's just a one line code that instantiates and sets an HttpUnauthorizedResult to the filterContext's result. The filter returns 401 and it is perfectly valid as per HTTP standards but how the Forms authentication module reacts to this 401 is kind of inconvenience. It redirects the user to login page even-though the user may already logged in. A better approach would be taking the user to login page if he is not at all authenticated and if he is authenticated but not authorized then redirecting him to a custom access denied page.

If the site has not forms authentication enabled then the programmer can control the action that has to be taken by handling the Application_Error event in Global.asax.cs. So this problem is only with the ASP.NET applications that uses forms authentication.

One way we can overcome this problem is creating a custom authorize filter and overriding the HttpUnauthorizedResult and check if the user is not authenticated then set 401 else set a redirect action result to a custom page. One thing we are moving from the HTTP spec is we are not setting 401 when the user is authenticated but not authorized though it's not correct but I see that would be fine compared to the inconvenience.

OK, enough theory! Let's complete the work and it is as simple as it is!

public class CustomAuthorize: AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest();
        }
        else
        {
            filterContext.Result = new RedirectToRouteResult(new
            RouteValueDictionary(new{ controller = "Error", action = "AccessDenied" }));
        }
    }
}
Listing 2. Overriding HandleUnauthorizedRequest

We are checking if the user is not authenticated and if it is then do the default way else redirect the user to the AccessDenied action of an Error controller.

That's it! Enjoy!!

Like to hear comments from you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

After2050
Software Developer Trigent Software Private Limited
India India
I'm a software developer from south tip of India. I spent most of the time in learning new technologies. I've a keen interest in client-side technologies especially JavaScript and admire it is the most beautiful language ever seen.
 
I like sharing my knowledge and written some non-popular articles. I believe in quality and standards but blames myself for lagging them.
 
I believe in small things and they makes me happy!
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinmemberJohn B Oliver1-Aug-12 13:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 15 Apr 2014
Article Copyright 2012 by After2050
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid