For many, security can be an afterthought. When it comes to designing a project, emphasis tends to placed on a what a project will do rather than in what circumstances it can do it. Often is can be difficult to deal with when later.
You cannot avoid the fact that security is a cross app concern, all the way from deciding how the UI should be displayed to how data can be queried/persisted. How best to approach this then?
Unfortunately the common approach is to start to split functionality, so, only a particular group can do “this”, lets call them something that vaguely indicates who should access this functionality, say”admins”, and mark those users in some persistent way, giving them a role. We then begin to query this ending up with all sorts of checks across our entire application, typically saying if a user has a particular role, they can do “this”.
To decide on a best approach we need to first recognise our problems.
In the scenario described, the first major problem is that our control is in no way inverted. We cannot ask a central service, given a user can they do/see this? We can only say do they have this role. If we decide to change our roles… argh! Even if we just add roles, we need more checks, lots of code to add again. If instead of checking a role, we could actually pass a description of what was happening to a central service, call it an operation say, something that is inherent to that part of the code or UI, that defines whats actually happening, we could make wholesale changes to who could do what and that code would remain unaffected. All that method would care about about is passing an operation, whats actually happening then, and then getting an answer back, yes or no.
The second major problem is that our roles will eventually become inherently linked to data. Not only do we need to stop people doing “this”, in any complex application we need to stop them doing this under particular circumstances, or even stop them seeing something. This will be typically related to data and means we will want to augment queries based on these restrictions. In our role scenario we essentially have operations, and query information baked together as one. Unless we separate them somehow we’re going to end up with LOTS of roles. Ideally we need to be able to to ask our central service, can this user do this and get back, yes but only with this data.
These problems only increase when we want to start letting our clients define/configure permissions themselves…
BUT what if we could write something like?
public bool IsAllowed(Operation, User, Entity);
Enter Rhino Security. It is an enterprise security framework that integrates with NHibernate, built by Ayende Rahien. It attempts to solve these problems by making, among others, 3 key distinctions:
- Security is about operations.
- Simplicity/flexibility is key, the burden is on the infrastructure, after all data is cheap.
- Permissions should do the work of enhancing queries for you.
Sounds good? I know.
Next post