IIDENTITY and Authorization design questions

IIDENTITY and Authorization design questions

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


dstarkey posted on Thursday, September 14, 2006

I am working on an employee main application.  My problem is how to incorporate an inordinate amount of possibilities (roles) into the business objects.  Background information, my understanding is the PTIdentity class retrieves a role list that pertains to a unique user which is used by the bo's to grant authorization to bo properties etc...  I hope this is true or I am totally missing the point!  My application can access multiple companies, so the authorization levels would become way to large to statically write each one into the various bo's.

Here is a sample of my problem.  We have a userXrole table that defines the following fields.   EmpID, Company, Division and RoleId.  So the PTIdentity object retrieves this role list from this table.  My EmpID would generate over 400 rows in this table since I have a "Internal" roleID and therefore have access to all of these companies, and that is just my individual entry.  What happens when the companies double in volume?  So how do I 1) limit the size of this role collection 2) incoportate all of these roles within my bo in an efficient manner??  Does anyone have a working sample of how they solved these two problems??? 

Should I pass in parmaters to limit the size of these two (role list, and bo list of Authoriztions)collections?  How can this be done?  Can the AuthorizationRules be built dynamically?  What is the best way to do so with my application?  Anyone encounter any problems similar to these?  I am still fairly new to the framework and any help or samples are greatly appreciated.  I am very much stuck on this right now.  For instance it is very common for 1 person to have different roles within the same company based on division, yet another permutaion.  Please help!!!

Thanks Don

RockfordLhotka replied on Thursday, September 14, 2006

I think you need to decompose the problem a bit more.

It sounds like you have an application with a set of roles - a large list, but finite and (for a single company) probably not unmanagable?

And then you have many companies - which I take it are effectively "instances" of the application. So that list of roles exists on a per-company basis - but is the same list each time?

Remember that authorization is business logic - very similar to validation rules really. In the simplest form this is merely an IsInRole check. But in your case it is almost certainly a multi-part check of some sort.

This is why CanReadProperty and CanWriteProperty are Overridable/virtual - because the simple role-based model doesn't work for all applications. Sometimes you need do have more sophisticated logic.

It sounds to me (if my assumptions are correct) that your custom Principal object needs to store a Dictionary of companies, with a List of roles for each company. That way you can have a more complex IsInRole that gets the right role list for the current company, and then checks the role.

In other words, I'm guessing that the action of "Edit Customer Data" requires role X - for all companies. It is always X. But a given user might be in role X for company 1, and not for company 2.

So your IsInRole needs to see if the current user is in role X for a given company.

To do this, you'll most likely need a custom Principal object, with an overload of IsInRole - and then you'll need to subclass the CSLA base classes to create your own custom base classes that override CanReadProperty and CanWriteProperty to call your more sophisticated IsInRole method.

maurera replied on Thursday, February 15, 2007

I have done a bit of searching on the forums regarding implementation of custom security and have seen a lot of good ideas.  We have a similar need to what the OP of this thread is looking for. 

We will have a User Table, Role Table, userXrole table, userroleXsubteam table, and a userroleXfacility table.  Basicaly, users will have roles associated with them.  A user that has a Role will require some "context" data to determine if the user can perform the Role.  This "context" data is defined by the userroleXsubteam and userroleXfacility tables.  The Role record will have two bit fields "ReqFacility", "ReqSubTeam" to determine what context the roles need.  For example, one Role may be "FacilityRecipeAdmin" whose context would require a FacilityID.  Where as Role "FacilityOrderAdmin" may require a FacilityID and a SubTeamID.  Or, you could aslo have a "RegionalBuyer" that would only have a SubTeamID context. 

In other words a user could be a "FacilityRecipeAdmin" in facility 1 and 2 and\or a "FacilityOrderAdmin" for Facility 1 subteam 100, facility 1 subteam 200, and facility 2 subteam 100 and\or a "RegionalBuyer" for subteams 100, 200, and 300.

Ideally we would like to raise an error if the Business developer, or UI developer attempts to check a Role without using the proper context data.  Or an administrator tries to assign a Role to a user without supplying the proper context information.

From what I can gather on the forums, it would make sense for us to have a custom Principal object with a more complicated Overloaded implementation of IsInRole...there is some debate in house as to whether or not we should have the Overloaded IsInRole definition match the IsInRole definition on IPrincipal, or use our own "Context" type as a parameter so that if another Region wanted to use Active Directory to manage there roles it would be (in theory) less painful for them to accomplish a modification...but that is not the problem I am wrestling with right now. 

I think I follow what Rocky is saying as far as subclassing the base classes to override CanReadProperty and CanWriteProperty...however, unless I am missing something, it looks like they are not the methods that are calling IsInRole off of IPrincipal (or what would have to be a direct cast of ApplicationContext.User to the custom Principal class in our case).  It looks like the IsReadAllowed, IsWriteAllowed methods off of the RolesForProperty class is actually making the call to IsInRole. 

So, does that mean that we would have to write our own versions of the RolesForProperty class and the AuthorizationRules class to use from our newly subclassed BusinessBase...which really doesn't sound right to me.

I guess my question is, are we heading in the right direction or are we totally off base here.

I must either not understand something, or am missing something...maybe it’s the late hour.  I think I will sleep on it and see if it makes more sense in the morning, any insight would be appreciated.

JoeFallon1 replied on Friday, February 16, 2007

There is some danger in using something other than IsInRole.

I use it plus something I called HasPermission which is finer grained.

I ran into this exact issue. The framework only calls IsInRole. Nothing else. This means that if you want to check something else you have to re-write that entire part of the framework (or else modify CSLA directly - which you want to avoid).

I spoke with Rocky about this and he understands the issue.

In a future version he may define a Delegate that calls IsInRole by default but you could then replace that implementation with HasPermission as long as the signatures match.

But there is no guarantee if or when it will make it into the framework. Which is why I am giving you this warning.

Joe

 

RockfordLhotka replied on Friday, February 16, 2007

Also, consider this thought:

 

If you never use IsInRole, because your whole model is based around “permissions”, then you can safely repurpose IsInRole to check your permissions list – thus eliminating the need to add a HasPermissions method. A lot of people do exactly this, because it is the simplest way to get the desired behavior.

 

The only thing that would stop this, is if your authorization rules are so complex that you sometimes check for the user’s role, and other times check for the user’s permissions. In that (pretty rare) scenario you obviously can’t use IsInRole to check permissions, because you actually need it to check for roles.

 

Rocky

 

 

From: JoeFallon1 [mailto:cslanet@lhotka.net]
Sent: Friday, February 16, 2007 10:16 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] IIDENTITY and Authorization design questions

 

There is some danger in using something other than IsInRole.

I use it plus something I called HasPermission which is finer grained.

I ran into this exact issue. The framework only calls IsInRole. Nothing else. This means that if you want to check something else you have to re-write that entire part of the framework (or else modify CSLA directly - which you want to avoid).

I spoke with Rocky about this and he understands the issue.

In a future version he may define a Delegate that calls IsInRole by default but you could then replace that implementation with HasPermission as long as the signatures match.

But there is no guarantee if or when it will make it into the framework. Which is why I am giving you this warning.

Joe

 



Copyright (c) Marimer LLC