Security Considerations

time to read 4 min | 709 words

Security is always an annoyance, on the one hand, you really need to do something about it, on the other hand, the moment you do, the entire application breaks. It is often useful to build the security infrastructure at the first stages of the application, but that is not always possible.

For various reasons, I just now got to the point where I could deal with security, and I had a radically different set of requirements than I had at the beginning of the project. That left me wondering how to ensure that I didn't forget to add security in the proper places.

A while ago I wrote an article that has shown how you can add generic security features directly into the data access layer. Security was very simple, you literarily could not break the security, because the data access would filter / reject anything that you didn't have authority to do.

The problem with this approach is that it assumes something about the domain. Let us say that I use the usual CRUD permissions. Now, I have business rules (themselves entities) that can be attached to a policy. A user has access to view / edit the policy, but is not allowed to view /edit the associated business rules.

Can you guess what happened when you turn on the security mechanism?

Ouch! The system would behave as if the business rules did not exist if (and only if) the user didn't have permissions to edit / view the business rules. This created the amusing situation where the admin is able to test the business rules but the user's actions completely ignore them. The client wasn't amused, and I learned an important lesson.

I am currently using a two tiers approach for security, I have the authorization service, which contains the logic for allowing/denying permissions from the user:

image

Note that the authorization service has a lot of methods per scenario. The idea is that all the methods call to the IsAllowed() method, but it leaves me with a much nicer syntax to use. I don't have enough permissions that this approach would be a problem.

Then, in my abstract controller, I have defined:

///<summary>
/// Validate that the user is allowed to use this controller or
/// this use case
///</summary>
public abstract void AssertUserHasPermissions();

Now, I must take action in each and every controller, and decide how I would treat the security implications at each use case.

Here are a few examples:

// In: ChangePasswordController
public override void AssertUserHasPermissions()
{
    // Well, anyone can change their password
    // nothing to assert
}

// In: BaseAdminController
public override void AssertUserHasPermissions()
{
   if(AuthorizationService.IsAdmin==false)
      base.AccessForbidden(Resources.YouAreNotAnAdmin);
}

// In: PolicySearchController
public override void AssertUserHasPermissions()
{
   // well, basically anyone can try to search for policies
   // security here is done by the finders for each scenario.
   // AbstractPolicyFinder has AssertSearchingForAsscoiatedCustomersOnly
   // and FilterSearchResultsBasedOnAuthorization methods to handle the
   // security there.
}

The advantage, I am making explicit the security decisions that I am making, and I make the action very explicit.

It does mean that I am going to return tomorrow for an application that is compromised of a login page and an access denied page, though :-)

(One thing that I would like to recommend is to always have a usable (not necessarily pretty, but usable) UI for the security, and ton of logging.)