RxBA - Role Based Authorization or/and Resource Based Authorization

RxBA - Role Based Authorization or/and Resource Based Authorization

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


tiago posted on Thursday, January 28, 2010

Dear all,

CSLA.NET supports Role Based Authorization (RoBA on this post). Given an object, a user is granted authorization to perform actions on that object depending on the role list of the user. A role might be denied access to that object (not even read access), another may read but not change anything, another may read but change only some properties, etc. I admit that must be the most common model on enterprise applications.

The point is RoBA isn't the only model of authorization. Sometimes one needs Resource Based Authorization (ReBA on this post). "Like when" you might ask. Like a Document Management System. There are documents I have access because I'm the guy that checks an invoice can be payed (that's my role). I have access to other documents because I belong to the Boston location (ok, we can think of it also as a role) but some other documents I have access because it's me (all documents on my HR file), whatever my present location or role in the company might be.

To make things even more complicated, I work on a TV station as a producer. There are a lot of producers on my TV station. Some aren't producing anything at all (they are friends with the station owner and just play golf with him), others are producing news, sports, etc. Their role is "producer". Producers have full access to all show objects (unrestricted authorization). But not for all shows, just for the shows they are assigned to.

I think it's not a good idea to create a new "producer" role for every new show. The answer looks a lot like "role by resource": the "producer" role has an authorization profile that applies only to assigned resources. For the unassigned resources, the "producer" role has no special autorization: just the same as any other ordinary role in the TV station.

Now take the "director". He has more restricted authorization level on the show objects but on the other hand - and just to make things worst - suppose the "director" is assigned on a daily base (that is more or less true). The next day he is no longer director on this show, but he must be granted read only access for the objects of the shown he was assigned as "director".

How should I handle authorization on my TV station management application? Do I need to use both RoBA and ReBA? How can I do it with CSLA.NET?

RockfordLhotka replied on Thursday, January 28, 2010

CSLA supports authorization at two levels: type and property.

At the type level, authorization indicates whether you can create/fetch/save/delete a type of object. Not a specific instance, just a type. So this can't be adapted to a context-sensitive model because there's no instance, just the type.

Arguably you could make save/delete be context-sensitive, because you have an instance. But you can't ever make create/fetch context-sensitive, because you don't know if the operation is legal until after the operation is complete. Until you have the actual object, you can't find out if the user was authorized to do the operation you just did to get the object :)

If you want context-sensitive create/fetch/save/delete operations, my recommedation is to implement them in the DataPortal_XYZ methods, where you have context, and can prevent the operation from completing if the user isn't authorized.

At the property level, you can easily extend the existing role-based behavior by overriding CanReadProperty() and CanWriteProperty(). Overriding these methods allows you to add context-sensitive rules for specific objects and properties, while allowing other objects and properties to continue to use the normal role-based model.

tiago replied on Saturday, January 30, 2010

RockfordLhotka:

At the property level, you can easily extend the existing role-based behavior by overriding CanReadProperty() and CanWriteProperty(). Overriding these methods allows you to add context-sensitive rules for specific objects and properties, while allowing other objects and properties to continue to use the normal role-based model.

This is most appropriate in several use cases.

When editing the object
1) if current user is the creating user, show this field or allow him to edit that field
2) if object is in workflow step "abc" and user is in role "def", allow him decide the next workflow step (edit a property or click a button)

RockfordLhotka:

(...) Until you have the actual object, you can't find out if the user was authorized to do the operation you just did to get the object :)

But as you said, properties are useless for enabling/disabling user access to an object on a more radical approach:
3) user can't list this object because he isn't assigned to this object
4) user can have read only access but not edit access to this object because workflow step is "ghi"

Use cases 2) and 4) can be solved if I map a role to each workflow step. So they fall under the RoBA issue that is nicely solved by CSLA.NET.

Uses cases 1) and 3) are ReBA and 3) isn't solved.

Just for making this subject clear for CSLA starters, the point here isn't "how to show a list that shows only the objects I want the user to have access" (use case 3). This is esay enough to do if you transfer your business logic to the UI layer. Suppose you are using Web Services the fecth the same list. How do I return this list in use case 3?  (see next message)

ajj3085 replied on Monday, February 01, 2010

#1 is solved by overriding CanReadProperty / CanWriteProperty.

#3 is solved in the DataPortal methods; usually by using the current users logon id to filter the list returned by the data.  There's not much Csla can to directly to help you with this, but the BO can certainly have such logic built in.  It's still a business rule... just happens to be enforced in the DP_F method, which I see nothing wrong with.

tiago replied on Wednesday, February 03, 2010

Let's face it.

THUS

It's as simples as that.

CLSA.NET business object model has no provisions for full resource access control rules in the business layer. This is also a very simple fact.

There are 2 issues involved:

1) How can it be done in CSLA.NET? Rocky already said it can be done in the DataPortal (aka DAL). That means business logic will bleed to the data layer. That isn't a "Best Practice" for sure. It breaks some goals of OO design, namely some CSLA goals.

2) Is this solution acceptable? That's another issue, another answer and that's really the point.

The n layer model was adopted not because of some "original sin" issue but because it makes development and maintenance easier (read less expensive). The data access layer should care only about handling data access for storage purposes and shouldn't care a bit about business rules. Using this solution means that when business rules change, depending on the specific business rule that changed, I must change code in one layer or the other. It also means that when switching the DAL from SQL Server to Oracle one must sure the business rules inside the DAL aren't affected and they still behave the same way. This is all old news. What's the conclusion? In fact I can't say. But I think this deserves a good discussion of concepts so the concrete implementation can have a good design.

In fact it's hard to find discussion material about resource based authorization in the web. I imagine that isn't a very common problem. Or maybe it is, but is ignored most of the time because it's hard to solve.

In A Fairly Capable Authorization Sub-System with Row-Level Security Capabilities (AFCAS) a resource acces method is discussed that handles ACL for users, groups and also can do hierarchy. I don't see any problem in implementing this model outside the business layer: it's a do or don't. Either you implement it or you don't implement it. No dependencies - except the database server - and no changing rules here. Once you are sure the sub-system is working, no further testing and maintenance is needed.

In fact AFCAS is quite interesting at the conceptual level as it plugs after the DAL, showing a view of the data that depends on the user that is using the database. The database is no longer the same for all users but each user sees a virtual copy of the database that is composed only of the data that he is allowed to see. This model provides a transparent base for whatever object model you put on top of it.

When I wrote the opening message I was expecting that some other solution would come up that wouldn't be database dependent. That's the only problem of this solution, and it's a very big problem!

I suppose this solution can be moved outside the database to a new layer that should sit between the DataPortal/DAL and the database server. We can argue about the bandwidth that is consumed "for nothing" if we get all the data only to throw it out as the user has no access to that data. But that really isn't an issue, as one can always make a query (not a stored procedure, just a plain query) that only gets the data the user is allowed to see.

Of course, you can make it part of the DAL or make it part of the database. "Sitting" betweeen those two layers means you can put it in one or the other.

The point here is the concept: resource access control is a special case of a business rule that acts as a filter of the data, creating a virtual database for each user.

tmg4340 replied on Wednesday, February 03, 2010

This delves a little bit beyond CSLA...

I'm betting that there isn't much "reference material" on this largely because .NET wasn't designed to do this in an "elegant" fashion.  .NET's security concepts revolve around the Principal/Identity (i.e. role-based) concept.  Microsoft is working on a new solution (the Windows Identity Foundation framework), which is claims-based.  Presuming you want to wait until .NET 4.0, this might be something to look into.

Of course, it's also a "version 1 tech" from MS...

From my perspective, the question is whether you want to maintain the "purity" of your system, or the performance of the system.  If performance is an issue - or you have a particular aversion to returning a potentially large set of data from the database that you're going to throw away - then you don't really have a choice: some section of your resource-based rules must exist "on the database".  Whether you use AFACS, SQL Server's row-/column-level security functionality, or a code-based solution (either stored procedures or dynamic SQL), your data layer will be "infected" with business rules.

I'm also not entirely sure I agree with labeling security-related functionality "business rules".  Security is one of those cross-cutting concerns that, IMHO, extends beyond your business layer.  The ruleset that defines the overall security of your application does come into play in pretty much every piece of your application.  The fact that CSLA encapsulates some of that into the framework design is a convenience to let you plug your security model into the workings of your business objects.  A necessary convenience, but a convenience nonetheless.

- Scott

RockfordLhotka replied on Wednesday, February 03, 2010

I'm open to proposals tiago. Exactly what would you think CSLA could do to help address your situation?

Define an interface? Implement some abstract instance-level methods that you could override?

Either way, CSLA itself wouldn't really do anything meaningful - it would just define places for you to write your code.

Since we're talking about context-specific rules here, the actual implementation of anything useful would be type-specific - not role-based right? So there's virtually nothing CSLA could do to help.

Though maybe I'm missing something obvious - which is why I welcome concrete proposals for exactly what you think CSLA could do.

ajj3085 replied on Thursday, February 04, 2010

tiago:
1) How can it be done in CSLA.NET? Rocky already said it can be done in the DataPortal (aka DAL). That means business logic will bleed to the data layer. That isn't a "Best Practice" for sure. It breaks some goals of OO design, namely some CSLA goals.

I view the DataPortal methods as part of the business layer, and not the DAL.  The DAL would be my Linq2Sql object, linq2Entity, any web services that fetch or store data, etc.  The BO knows how to use the DAL. I think the DataPortal should be named something else, because its purpose is really to allow you to run code on another physical layer, if you choose to, with the appropriate context intact.  You could use it to run some complex calculations on a fast server if you so choose, it doesn't have to talk to a database at all.

Do you see any problems with the fetch method knowing how get a particular invoice from a set of invoices?  How is the security you want to apply any different?  Its just another criterion the BO uses to ask for the relevent data. 

But my Linq2E objects don't change based on whether or my BO filters based on someones logon id.

tiago replied on Saturday, January 30, 2010

RockfordLhotka:

If you want context-sensitive create/fetch/save/delete operations, my recommedation is to implement them in the DataPortal_XYZ methods, where you have context, and can prevent the operation from completing if the user isn't authorized.

Right.

Given the use case:
A user can only know of objects he is assigned to. For other objects, the user is not only DenyRead but also DenyExistence. When fectching a list of objects I can do it in two different ways:
a) fectch every object from the DB and filter out the ones that shouldn't be there
b) have my SELECT query include only the objects I know are legal (how do I know it? this should be a business rule...)

I prefer b) for speed but that's a bit beside the point.

RockfordLhotka:

At the type level, authorization indicates whether you can create/fetch/save/delete a type of object. Not a specific instance, just a type. So this can't be adapted to a context-sensitive model because there's no instance, just the type.

In CSLA.NET something like DenyExistence is a type level authorization: user "jkl" has no access to objects of type "mno" This is ReBA but by resource type, not by resource instance.

To solve the Resource Based Authorization issue, I need to transfer part of my business logic ouside the Business Layer. That's the point.

RockfordLhotka replied on Saturday, January 30, 2010

I think the important thing is that you can't implement context-sensitive rules without the context.

So if the context is contained in the object, then the object must exist before the rules can be applied.

So applying context-sensitive rules to create/fetch (and immediate delete) operations poses a very real challenge.

You can always override Save() to apply context-sensitive insert/update/delete rules - that's pretty easy, and the code is in your business object (typically on the client - so before paying the cost of getting to the app server, etc).

But again, create/fetch require that context - so you have to get the context first... In short, you can implement these rules in your business layer, but they have to run in the server-side parts of your business layer (the DataPortal_XYZ methods).

You can provide context to your DataPortal_XYZ methods or DAL easily enough. The criteria object is context, and don't forget about Csla.ApplicationContext.ClientContext - which is a good way to provide limited amounts of context. As is the ApplicationContext.User object (custom principal).

RockfordLhotka replied on Thursday, February 04, 2010

The thing is, there are no less than four models for implementing data access code:

  1. DataPortal_XYZ; DAL code in the DP_XYZ methods
  2. DataPortal_XYZ; DAL code in separate assembly invoked by DP_XYZ
  3. Object factory; DAL code in the factory object
  4. Object factory; DAL code in separate assembly invoked by object factory

In all cases it is fine to put business logic in the DP_XYZ, and maybe in the object factory (though I think that's iffy). But if you are going to do so, it is best to use models 2 or 4 so the DAL is cleanly separated from this business logic.

Really with an object factory, if you need business logic to run on the server, the object factory should invoke methods on the business object that implement that logic. So the logic isn't in the factory, it is in the business object - and is just invoked by the factory object.

tiago replied on Wednesday, February 17, 2010

Scott, Andy, Rocky

Thank you all for the refreshing discussion

I guess Scott is right. .NET wasn't made for Resource Based Authorization.

I agree with Rocky: there is nothing CSLA could do to help to solve this use case.

As I said in my previous post, I'm planning to solve it at the database level.

Copyright (c) Marimer LLC