We can take it a step further and decide that we don't want to explicitly state this, and just assume it by convention.

A while ago I decided to make a system work in this exact fashion. Of course, I am a big believer of convention over configuration, so we defined the following rules for the application:

Need to secure Read / Write / Delete

Need to support custom operation as well, like "Assign work", "Authorize time sheet", etc

Developers will forget to make security calls, we need to develop a system that protects us from this.

We built a really nice implementation that hooked directly into the container and the data access later, you literally could not make a security breach, because you were always running under the context of a user, and the data was filtered for you by the data access in a generic fashion. For that matter, we didn't have to worry about authorization in the business code, we made in memory modification and then persisted that. If we had a security violation, we simply showed an error to the user.

We didn't have to define anything in the code either, it was all convention based and implicit. The only complexity was in configuring the security system itself, but that was the nature of the beast, after all. We though that we found the ultimate security pattern, and were quite pleased with ourselves. Until we started user testing. Then we run into... interesting issues.

We had the idea of a rule in the system, which could be used by the administrators to set policies. It worked just fine in our testing, until we started to get impossible errors from the users. I think that you can understand what it was by now, right? (Yes, the usual, developers always test as admin)

Normal users didn't have permissions to read those rules, but the system really needed them to perform core parts of its tasks. We are always running under the user context and we are always making the security check. The system was designed, up front, to be very explicit about it. Now we found that there really were reasons where the system needed access to the entities without performing those security checks.

Another "interesting issue" that came up was the issue of information aggregation. As it turn out, it was always the wrong idea to report that there is only a single entity in the system, just because the user has access to just that one. I'll let you draw the conclusion about the HR users that found out that they really couldn't see how many hours an employee worked in this month.

It was a big problem, and we had to scramble around and hack-a-lot the ultimate security solution that we so loved.

The security system had two major issues:

It was too granular.

It didn't have any operating context.

Since then, I have learned a lot about how to design and implement security modules, and my current design has the following requirements:

Security decisions are made on a use case level

Have a standard, enforced, approach of dealing with security

Make security decision easy to code.

How does this translate to code?

Well, first I need to define what a use case is in the code. For a web application, it is almost always at the page / request level, and that makes it very easy to deal with.

Since all the controllers in the application inherited from AbstractController, we had a single place that we put all the security checks. We still had to deal with security in other places, such as when we loaded data from the database, or wanted partial views, but this approach meant that we had remembered what was going on. If we needed to make security decisions elsewhere, we commented that in the assert.

But this was in a Rhino Igloo application, where by necessity we had to have a controller per page. Using MonoRail, we usually have a single controller that handles several actions, in which case I would tend to write something like this:

By context, do you mean data-based security where security is granular to an instance of an entity and not affected to a role that the user plays, whatever the instance of the entity it plays the role (performs the use case) against?

Are your security issues are related to having to grant extra roles (or rights) in order to have access to non-functionnal infrastructure (read rules)?

If so, one approach I've used in the past is to allow impersonation in my security framework so that user can be impersonated to a "system" account, account being able to read security rules.

In other terms, I wouldn't allow the user to directly visualize the rules but would definitely grant him some non-functionnal role that grants him the right to query (read) the rules for authorization purposes.

It's an extremely interesting topic. Security systems are usually something nobody wants to talk about (or deal with). And in many cases, role based approach works ... with a lot of compromises to the actual security.

But I would also like to hear how you push context to the security subsystem while using declarative approach as in your monorail sample. For example if action rules depend on the data action pulls out.

Indead ReadPermissions can be handled at the repository, but how would you protect some properties (like Salary) or prevent writing a property like CompanyName..Shouldn't that not be handled at Entiity level?