2

I am sorry for not posting any code. I am stuck at the design phase -that's why-

What I want to accomplish is: allowing system administrators of a 'Staff Task System' to dynamically set rights to a specific user/department to a specific action in run-time.

The rights are complicated. For example: They can restrict task assignment to employees, if User is the manager of the user's receiving the assignment. Also this manager can only view tasks if within same department and same location. Sometimes a task can require more than one person to approve and I don't only need to authorise these specific users dynamically, but also mark the task as approved after those specific users approved the task.

The above is just to give you an idea of what I am trying to implement. I am seeking an advice on the design-pattern/framework/direction to start implementing something like the above.

I am sure role-based is not the right answer. I started exploring Claim-Based authorization from .NET Identity but I didn't see much examples or tutorials on it.

  • 1
    Have a look at Attribute-Based Access Control – devnull Nov 21 '16 at 9:37
  • @devnull. Sounds good! if you have implemented this method, can you venture a sample of the implementation. Did you claim-based authorization ? Custom Attributes ? or just another authorization service to run the checks ? – e7na online Nov 21 '16 at 9:41
  • And is there's a way to specify if rules can have an 'AND' relationship or 'OR' relationship – e7na online Nov 21 '16 at 9:46
  • Yes, AnyOf and AllOf elements, as defined in XACML, allow you to build expressions with AND and OR – devnull Nov 21 '16 at 9:52
  • 4
    Task approval (as you explained it) is a business process, not a part of AAA. – Vlad Nov 21 '16 at 10:33
1

The complicated thing in you concept is that permission is also based on table data content. (i.e. if within same department and same location)

I have seen a permission system were each usergroup has table-specific sql-where that will be appended to every sql query.

Example:

role:department-a-manager; filter:(Adress zipcode:45xxx),(Store departmen:a)

this means when a "department-a-manager" selects data from the adress databse table then the dadabase logic adds and zipcode like '45%' to sql-where.

An other aproach whould be to create role specific databaseview that have the sql where inside.

example

the databaseview adress-department-a-manager is defined as select * from adress where zipcode like '45%'

0

The problem description basically excludes the simple roles and claim based calculations. Claims are basically a bunch of facts about your user that are static. You can do lots of fun things with that, but you can't easily add and remove claims at runtime.

You'll probably have to extend the AuthorizeAttribute to enable dynamic authorization.

The attribute has a callback method that you would implement to do your lookups and apply the rules. A very rough example would be like this:

public class AuthorizeStaffTaskAttribute : AuthorizeAttribute
{
    public string Something { get; set; }

    protected override bool Authorize(HttpContextBase context)
    {
        MyCustomUser user = context.User as MyCustomUser;
        return user != null && user.CanDo(Something);
    }
}

The thing is that attribute declarations require your expressions to be constant. You can use an enum, a magic string, etc. Nothing that is calculated. Of course you can declare your Something as a Linq Expression and evaluate that in your Authorize() callback.

This can get you started at least.

0

Lambda expressions give you that "on the fly" combining power you want! I have been deployed solutions like that, with relational security on content collections. Define security groups and permissions using LINQ criteria, and then filter collections based on these security rules like:

public IQueryable<TContent> Filter<TContent>(
    IQueryable<TContent> content, 
    string permission, TUser user) {
      var predicate = BuildPredicate<TContent>(permission, user);
      return content.Where(predicate);
}

The main concept behind this approach, is to use generics for 'security rules' definition, and lambda expressions to build predicates dynamically.

public static Predicate<T> Or<T>(params Predicate<T>[] predicates)
{
    return delegate (T item)
    {
        foreach (Predicate<T> predicate in predicates)
        {
            if (predicate(item))
            {
                return true;
            }
        }
        return false;
    };
}

public static Predicate<T> And<T>(params Predicate<T>[] predicates)
{
    return delegate (T item)
    {
        foreach (Predicate<T> predicate in predicates)
        {
            if (!predicate(item))
            {
                return false;
            }
        }
        return true;
}

The great implementation of such approach could be find here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.