Changing authorization based on role & property value?

Changing authorization based on role & property value?

Old forum URL: forums.lhotka.net/forums/t/5164.aspx


ajj3085 posted on Monday, July 28, 2008

I have a changing use case, which revolves around editing a department which belongs to a company.

Currently, we have a department name, type, phone & fax, and list of address information.  There's also an accounting id editable only by accounting.

What I now need to do is restrict department editing, based on these rules.
Some of these are clearly business rules that factor in role and property values.  Others are authorization rules.. which is where I'm not clear on.

Certainly an easy thing to do is override CanWriteProperty to check for roles and find an answer that way.  But is that the best way, or is there a better approach?  I don't think separate classes is an option here, because departments can be changed arbitrary from one type to another.

Thanks
Andy

ajj3085 replied on Monday, July 28, 2008

Another thing I'm not clear on the best way to handle..

The Department BO has child BO properties; a collection of addresses and a phone and fax number.  The children will need to adjust their rules so that only the appropriate roles can edit if the department type is of a restricted kind.

My current thought is to also override CanWriteProperty in these BOs, and to ask the parent the list of roles which are allowed to edit.  The list changes if the department BO's type changes.

Thoughts?

RockfordLhotka replied on Monday, July 28, 2008

This is why CanWriteProperty() is virtual, so you can add extra rules beyond smiple role checks to your property-level authorization.

You may also add checks in your factory (or DataPortal_Fetch()) methods to prevent the wrong user from retrieving an object they shouldn't see.

Obviously the per-type authorization can't handle this, because we're talking about instance-level values.

SonOfPirate replied on Monday, July 28, 2008

The way I've handled this type of situation may be more complicated and a bigger change than you want, so definitely go with the simplest option that works for you.

In my case, my security model resolves to the individual permission/privilege/right (synonyms - all depends on who you are talking to).  To manage organizational needs, I have "borrowed" the concept of Privilege Depth from Microsoft CRM's security model where a user may have been assigned a certain privilege, such as "May edit departments," but the final answer depends on their depth which can be one of the following:

When you combine the privilege with depth, you get tremendous control over who can do what.  Best bet, if you want to know more, is to do a web search on "Microsoft CRM Security".

HTH

 

ajj3085 replied on Monday, July 28, 2008

We are not quite that strict, although it seems like we could very well have that level of security later.

So how did you end up implementing this scheme?  Overriding CanWriteProperty?  Or something else?

SonOfPirate replied on Monday, July 28, 2008

I have an external security manager object that resolves the request.  So, my CanXYZProperty method, for instance, would delegate to the SecurityManager.HasPermission() method passing in the appropriate arguments.  I have two scenarios that I use: simple privileges or complex/specific privileges.

In the latter case, privileges are very detailed, usually one privilege per operation.  I find this most prevalent in service apps.  So, the app could have privileges like "Can Check-Out Projects", "Can Assign Resources" and so on.

In this case, for general inquiries, the only argument is the privilege being checked and authorization is simply checking if the user has that permission at that depth.

For per-instance checks, the object and the permission are passed and the state of the object can be evaluated to make sure that the user can perform the operation.  This is governed by additional rules such as ownership and assignment (ie, a user can't edit an object when it's been assigned to someone else).

With this approach, per-type authorization really doesn't apply.

On the other hand, with simple Read, Edit, Delete privileges, these can be granted on a per-type basis. When I do this, authorization is granted when the user has the desired privilege on the specified type.  For instance, per-type authorization would answer a question like: "Can this user edit Products?"

Likewise, for per-instance checking, we first check based on the object's type then apply the additional rules to make sure that can perform the operation on that specific object.  This answers the question "Can this user edit THIS Product?"

Make sense?  HTH

 

rsbaker0 replied on Monday, July 28, 2008

SonOfPirate:

I have an external security manager object that resolves the request.  So, my CanXYZProperty method, for instance, would delegate to the SecurityManager.HasPermission() method passing in the appropriate arguments.  I have two scenarios that I use: simple privileges or complex/specific privileges.

...

In this case, for general inquiries, the only argument is the privilege being checked and authorization is simply checking if the user has that permission at that depth.

For per-instance checks, the object and the permission are passed and the state of the object can be evaluated to make sure that the user can perform the operation.  This is governed by additional rules such as ownership and assignment (ie, a user can't edit an object when it's been assigned to someone else).

This sounds very similar to our requirement. We can't use the type-based roles as is because the object itself must be inspected to determine if the privilege applies (e.g. your depth concept).

Are you using the CSLA role mechanism at all or is your implementation completely separate?

SonOfPirate replied on Monday, July 28, 2008

It is based on the CSLA implementation.  We have an additional interface (IUser) that our custom principal implements.  This interface defines the Privileges property which returns the list of privileges granted to the user (pulled from the db).  Then we've added a layer on top of the authorization code to allow the per-instance rules to be applied.

We still have the role-based methods in place, so if we wanted we could simply check for the role.  But, since our roles are dynamic and user-defined, it doesn't make any sense in most of applications to hard-code roles into the business objects.  A finite set of privileges does the job.

In the database, we relate each role to the privileges associated with it and the depth.  So, for instance, the "Project Manager" role is granted the "Can Create Projects" privilege at the Local depth while "Development Managers" are granted the same right at the Deep depth.

Our authorization methods check for role membership when a role (string) is passed.  Overloaded methods accept the privilege (custom object) and, optionally, the depth (enum) and checks for the specific permission at the given depth.  Another set of overloads takes the business object as an argument, delegates to the other methods for the Privilege Check then applies the additional logic to authorize access to the specific object.

I hope that answers your question.

 

ajj3085 replied on Monday, July 28, 2008

Ok, that's what I thought the answer would be.

My only hesitation was because of the Instance-level authorization rules.. that would be the other place I suspect this could work, and I thought I was missing something by not seeing how it would work with those kind of rules.

So I guess the question is.. when would you ever use instance-level authorization rules?  It seems like you either never would.. or there's some very niche place for them I don't see.

Thanks!
Andy

RockfordLhotka replied on Monday, July 28, 2008

There is no support for instance-level auth rules in CSLA.

 

I expect any instance-level rules would be in the factory methods and/or an override of Save().

 

Rocky

 

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Monday, July 28, 2008 12:23 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Changing authorization based on role & property value?

 

Ok, that's what I thought the answer would be.

My only hesitation was because of the Instance-level authorization rules.. that would be the other place I suspect this could work, and I thought I was missing something by not seeing how it would work with those kind of rules.

So I guess the question is.. when would you ever use instance-level authorization rules?  It seems like you either never would.. or there's some very niche place for them I don't see.

Thanks!
Andy


ajj3085 replied on Monday, July 28, 2008

Ok... then I'm really confused.. because I see these methods on Csla.Security.AuthorizationRules:

InstanceAllowExecute(string, params string[])
InstanceAllowRead(string, params string[])
InstanceAllowWrite(string, params string[])
InstanceDenyExecute(string, params string[])
InstanceDenyRead(string, params string[])
InstanceDenyWrite(string, params string[])

So by support do you mean those methods are hold-overs from previous versions, or that they should be removed (or have already been removed in the latest beta)? 

These method signatures are from Csla 3.5.0.

Andy

RockfordLhotka replied on Monday, July 28, 2008

Those are per-property authorization that are customized per-instance.

 

They are really a hold-over from the poor 2.0 implementation, and I don’t recommend their use. Xal tried to argue me into removing them, and I think he was right, but that’s all water under the bridge at this point.

 

Rocky

 

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Monday, July 28, 2008 1:49 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: Changing authorization based on role & property value?

 

Ok... then I'm really confused.. because I see these methods on Csla.Security.AuthorizationRules:

InstanceAllowExecute(string, params string[])
InstanceAllowRead(string, params string[])
InstanceAllowWrite(string, params string[])
InstanceDenyExecute(string, params string[])
InstanceDenyRead(string, params string[])
InstanceDenyWrite(string, params string[])

So by support do you mean those methods are hold-overs from previous versions, or that they should be removed (or have already been removed in the latest beta)? 

These method signatures are from Csla 3.5.0.

Andy


Copyright (c) Marimer LLC