Hallaghan
Hallaghan

Reputation: 1941

Authorization in ASP.NET MVC

I'm facing a case for which I've researched a lot and I still couldn't find a solution for. I've been given the task of finishing the implementation of roles in an ASP.NET MVC 1 application. The case here is against what is generally done when it comes to permissions in applications. Let's imagine that we have two roles, Operator and Manager, in a 5 pages website. Having an user which inherits the two roles, I want to allow and deny permission to view pages according to the following pattern:

For page 1, the Operator role allows the user to view but the Manager role denies; in this case I want to let the user having these 2 roles view the page;

For page 2, the Operator role denies the user to view and the Manager role denies as well; this is the only situation where I really want to deny a role, when both roles have denied the user from viewing the page.

So, whenever a user inherits multiple roles, what should determine that he can't view a page is a Full Deny (being denied for all his roles), and whenever he has a role that allows, even if all his other roles deny, he will still be able to view the page.

Does anyone know how is it possible to implement this?

EDIT:

Below is just a glimpse of how Authorization is done in our application, besides what's used in the sitemap. You can see the Rule below is using more than one profile. The situation I described above needs to work with the said implementation below.

<Rules xmlns="urn:artemis.runtime.web.security">
    <!-- RUNTIME -->
    <Rule roles="*" resource="^Artemis\.Runtime\.Web\.FilesController\..*" permission="Allow" />

    <!-- ABERTURA GERAL -->
    <Rule roles="*" resource="^Tagus\.Logistics\.Web\.Controllers\..*" permission="Allow" />

<Rule roles="Gestor Cliente,DUN" resource="^Tagus\.Logistics\.Web\.Controllers\.PlanningVsEffectiveController\..*" permission="Deny" />
</Rules>

Upvotes: 2

Views: 860

Answers (2)

BritishDeveloper
BritishDeveloper

Reputation: 13349

Authorize is used to decide who to ALLOW not deny. If you wanted to add deny functionality I guess you could make a custom Authorize attribute. Something like:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=true)]
public class DenyRolesAttribute : AuthorizeAttribute    
{
    public DenyRolesAttribute(string roles) : base()
    {
        Roles = roles;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }
        IPrincipal user = httpContext.User;

        if (!string.IsNullOrEmpty(Roles) && Enumerable.Any<string>(Roles.Split(','), new Func<string, bool>(user, (IntPtr) user.IsInRole)))
        {
            return false;
        }
        return true;
     }
 }

I made this up on the spot so make sure you test and tidy it up. Or maybe add an AllowRoles and a DenyRoles property so you can do a bit of both in the overridden AuthorizeCore method. You get the idea though

Upvotes: 1

Justin Soliz
Justin Soliz

Reputation: 2811

[Authorize(Roles = "Operator")]
public ViewResult PageOne(){
    return View();
}

[Authorize(Roles = "SomeOneElse")]
public ViewResult PageTwo(){
    return View();
}

If I understand correctly you dont wont either of the roles to view the second page?

Upvotes: 3

Related Questions