Custom Authorization With Asp.net MVC

The whole advantage with MVC over webforms is extensibility at every point. Extensibility, Extensibility, Extensibility.

Authorization is a very important and every web project has there own needs and requirements. Full customisation is paramount.

Here I will show you a simple way to customise your authorization.

In MVC attributes are used to protect a controller method, so we to get started all we need to do is inherit from the AuthorizeAttribute class.

    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            string[] users = Users.Split(',');

            if (!httpContext.User.Identity.IsAuthenticated)
                return false;

            if (users.Length > 0 &&
                !users.Contains(httpContext.User.Identity.Name,
                    StringComparer.OrdinalIgnoreCase))
                return false;

            return true;
        }
    }

This is the basics. We can put any logic we like in here and all we have to do is return false if for whatever reason the user should not be authorized. Then all you need to do is decorate the controller method with the new attribute as below.

    [CustomAuthorize]
    public ActionResult Index()
    {
        return View();
    }

From this simple example we can expand it with custom Roles.

    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        // the "new" must be used here because we are hiding
        // the Roles property on the underlying class
        public new SiteRoles Roles;

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException("httpContext");

            string[] users = Users.Split(',');

            if (!httpContext.User.Identity.IsAuthenticated)
                return false;

            SiteRoles role = (SiteRoles)httpContext.Session["role"];

            if (Roles != 0 && ((Roles & role) != role))
                return false;

            return true;
        }
    }

Where the SiteRoles class is defined as below.

    [Serializable]
    [Flags]
    public enum SiteRoles
    {
        User = 1 << 0,
        Admin = 1 << 1,
        Helpdesk = 1 << 2
    }

This can then be used be used as follows.

    [CustomAuthorize(Roles=SiteRoles.Admin|SiteRoles.HelpDesk)]
    public ActionResult Index()
    {
        return View();
    }

This will only allow the Admin and the Helpdesk Role access to the Index controller. If you don’t belong to one of these roles then you will be sent to the Login page.

The possibilities are really endless.
Happy coding.

Adam

33 Responses to Custom Authorization With Asp.net MVC

  1. [...] method, so we to get started all we need to do is inherit from the AuthorizeAttribute class.Click here to see the solutionHappy CodingAdam Posted: Feb 17 2009, 09:27 PM by schotime | with no comments Filed under: C#, [...]

  2. Rasmus M says:

    Nice post – helped me to a better understanding of the AuthorizeAttribute.

    What if I wanted a user who had already authenicated to be shown a “You are not authorized to view this page” when invoking the Index ControllerAction above, instead of being sent to the Login-page once again.

    If I understand the code above correctly, a user with the SiteRoles.User role could be sent to the Login-page twice if he first invoked a controllerAction having the CustomAuthorize attribute set to allow users with the role SiteRoles.User, and then invoked a controllerAction like the Index controllerAction in the code above (only allowing SiteRoles.Admin or SiteRoles.HelpDesk)…

    your thoughts?

  3. Achu says:

    Was looking for custom role in mvc. but if you use bit operator why not use

    var role (SiteRoles)httpContext.Session["role"]);
    return (Roles & role) == role;

    you don’t need to split string or trim it.

  4. Schotime says:

    @Achu
    I’m new to the whole bitwise operators.
    Gave that a try though and it works great.

    Will update the article to reflect this.

    Thanks.

  5. Schotime says:

    @Rasmus M
    I have had a look at this and you can do it.

    If you put the [CustomAuthroize] attribute on the controller and [CustomAuthroize(Roles = SiteRoles.Admin)] on the action method then only admin people will be allowed through. If you try to access the page with a SiteRoles.User then you will be sent to the “NotAuth” view. This can easily be changed.

    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
    // the “new” must be used here because we are overriding the Roles property on the underlying class
    public new SiteRoles Roles;

    private bool FailedRolesAuth = false;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
    if (httpContext == null)
    throw new ArgumentNullException(“httpContext”);

    if (!httpContext.User.Identity.IsAuthenticated)
    return false;

    string[] users = Users.Split(‘,’);

    if (!httpContext.User.Identity.IsAuthenticated)
    return false;

    if (users.Length > 0 && !users.Contains(StateManager.ContactName, StringComparer.OrdinalIgnoreCase))
    return false;

    SiteRoles role = (SiteRoles)httpContext.Session["role"];

    if (Roles != 0 && (Roles & role) != role)
    {
    FailedRolesAuth = true;
    return false;
    }

    return true;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
    base.OnAuthorization(filterContext);
    if (FailedRolesAuth)
    {
    filterContext.Result = new ViewResult { ViewName = “NotAuth” };
    }
    }
    }

    This will redirect you to the “NotAuth” view if you fail the role logic.

  6. Nizar says:

    Great post! I’ve been looking for how to implement custom authorization of MVC. Really like the idea of how you’re managing the SiteRoles and/or logic. Kinda confusing at first though.

  7. Ahrimaan says:

    Hi,
    Nice Post.
    Now i Understand how the AuthorisazinFlags work.
    Im sittin here and mull over a Problem:
    I want to use the Authorization Flag but in another Form
    Ive got a Detail View example /Report/1

    Now a User got more than one Rights
    Example : User a Rights 1 -> 1024 , 2 -> 2048
    the 1 stands for the view and the 1024 for a Bitmask. I want to mage it as dynamicle as possible.

    But i dont know how … Any Ideas ?

  8. Kevin says:

    Excellent tutorial. Now I’m a bit confused:

    Where/When would you set:
    httpContext.Session["role"]?

    ThanX in advance.

  9. Schotime says:

    I would set this on login usually.

    Thanks

  10. Shalin says:

    Excellent post.

    In addition I was looking for giving filtered access to records based on user’s location. In other words, in my application, users are assigned different locations (branches). I want user from a branch should be able to access records entered by users of that branch only. I have UserLocation and Location table to manage assignment. Could you please guide me for this.

    Thank you.

  11. Alex says:

    And how would I need to assign my custom role to a user I add in the controller?

  12. Thank you for sharing I wish I could go somwhere.

  13. bugeo says:

    Great!

  14. mroach says:

    Thanks for this; a great tip. I just wanted to mention that you can also put this on the Controller class as a whole if you want to protect all actions of the controller with less code.

  15. RredCat says:

    Thanks a lot.
    I’ve implemented custom membership provider that requests re-login when session is finished (form authentication still keeps me on page when I don’t have credential for retrieving data.. ) Your article helps me solve it.!

  16. Henrik says:

    This won’t work with caching, and will introduce a security flaw.

    See p.334/335 of Pro ASP.Net MVC 2 Framework.

  17. The_Smallest says:

    Thanks for post, helped in my digging.

    Please change comment in code
    // the “new” must be used here because we are overriding the Roles property on the underlying class

    new doesn’t override, it hides parent property.

    To override we use “override” keyword.
    To create new member and hide parent’s member we use “new” keyword.

  18. Kalle says:

    Hi,

    Thanks! I have implemented this solution and adapt it to my membership model.

    The problem is that

    string[] users = Users.Split(‘,’);

    always only contains “” ? Should it not have the name of the current user?

    BestRegards

  19. Schotime says:

    Does the Users array have any items in it?

  20. Dale says:

    Hey I dig your VS color scheme can you send me a copy of the settings? Also never seen the double << whats that?

  21. Garry says:

    The only issue I see with this code is that couldn’t you spoof what user group you belong to by simply changing your session role variable on the client side?

    If that’s the case, then would obfuscating the role session variable get around the issue by removing the predictability of your role ids?

  22. Schotime says:

    @Garry,
    You cannot change the session variable from the client side.
    It never gets sent to the client

  23. Garry says:

    @Schotime

    Ah that’s right. I got my session storage and cookie storage mixed up :) .

  24. Manthan says:

    THANKS A LOT

    This post helped me a lot..

  25. [...] stumbled across this web post about making a custom Authorize attribute. Notice how they are checking the logged in users role [...]

  26. Stephen says:

    WOW! Thank you so much for this article. This helped me SO much!

  27. Misi Moisei says:

    Great article. :)
    Is it ok if I populated the list of users from my model(I have a custom table users), not from my AuthorizeAttribute.Users list ?

  28. Naomi says:

    I have the same question as Misi. I have my own Operators table and I want to use it instead to authorize access to the site. Can you please show how to implement something like that?

    Thanks again for the article, very interesting.

  29. Arthur says:

    Good work. I applied your idea in my applications. Thank you for your sharing so good customizing authority solution.

  30. afreeland says:

    What is the purpose of the shift operator? Not sure I understand the significance of that piece.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>