Access Control in ASP.NET MVC depending on input parameters / service layer?

First of all, I think you already half-way figured it, becuase you stated that

as first I’d need a different role for every product, and second I won’t know which role to check for until I’ve retrieved my Product from the Repository

I’ve seen so many attempts at making role-based security do something it was never intended to do, but you are already past that point, so that’s cool 🙂

The alternative to role-based security is ACL-based security, and I think that is what you need here.

You will still need to retrieve the ACL for a product and then check if the user has the right permission for the product. This is so context-sensitive and interaction-heavy that I think that a purely declarative approach is both too inflexible and too implicit (i.e. you may not realize how many database reads are involved in adding a single attribute to some code).

I think scenarios like this are best modeled by a class that encapsulates the ACL logic, allowing you to either Query for decision or making an Assertion based on the current context – something like this:

var p = this.ProductRepository.GetProductById(id);
var user = this.GetUser();
var permission = new ProductEditPermission(p);

If you just want to know whether the user can edit the product, you can issue a Query:

bool canEdit = permission.IsGrantedTo(user);

If you just want to ensure that the user has rights to continue, you can issue an Assertion:

permission.Demand(user);

This should then throw an exception if the permission is not granted.

This all assumes that the Product class (the variable p) has an associated ACL, like this:

public class Product
{
    public IEnumerable<ProductAccessRule> AccessRules { get; }

    // other members...
}

You might want to take a look at System.Security.AccessControl.FileSystemSecurity for inspiration about modeling ACLs.

If the current user is the same as Thread.CurrentPrincipal (which is the case in ASP.NET MVC, IIRC), you can simplyfy the above permission methods to:

bool canEdit = permission.IsGranted();

or

permission.Demand();

because the user would be implicit. You can take a look at System.Security.Permissions.PrincipalPermission for inspiration.

Leave a Comment