How to handle permissions/security in the Clean Architecture

4,026 views
Skip to first unread message

sylvain....@gmail.com

unread,
Jun 18, 2013, 4:18:55 PM6/18/13
to clean-code...@googlegroups.com
I searched on the subject but there seems to have little information about where, in the model, you handle security considerations.

For example:

You have a web application where a user is logged in. This is handled by cookies by the framework and in your controller, you get the User object representing the logged in user. You then want to handle the GET request, but for sure does not want to handle the security consideration in the controller. So you give to your interactor the User doing the action, and other parameters, right?

Then, do you use the interactor to filter out or block the data returned or accepted as input or do you push the security check in the entities? That means every entity will have to know who is doing the method call, which would add the User parameter to nearly every method of every entity. The entities can also access a singleton to get the current user but this is dangerous because if it is not reset appropriately, the last user can be used instead (and this is a global, which is bad). I think this approach would make a bleed of User and permissions everywhere.

Maybe the confusion comes from the fact that a User can be a legitimate business entity. This User can have Picture, and Message for example and they will have to be present as entities and saved in the persistence layer. But at the same time, we want to know which one of these User entity is doing the interaction with the interactors. I guess at the "Entities" layer, you would not handle the security and allow the caller to add/remove/update any Picture or Message for any User. Then you would verify if the logged in User can really do that in the "Use Cases" layer. This way, if you code an automated script doing major changes to entities in batch, you won't have to provide an admin User but simply access entities directly.

What do you think and how did you deal with this in your applications?

Sylvain Chamberland

unread,
Jun 19, 2013, 9:47:49 PM6/19/13
to clean-code...@googlegroups.com
I'm experimenting myself with the clean architecture, but I've also given some thought to the question of security.

It all depends on what those security restrictions are. I'd consider making the User object a dependency of the interactor, and use constructor injection with a dependency injection tool. In my web framework, the MVC controller already provides me with a User object with its roles/groups (which I associate to permissions). And I'd consider making the entity responsible for determining the user's level of access, since it seems to me that it's a business rule, not an application rule.

I'll give an example from Mark Seeman's book, "Dependency Injection in .NET", from chapter 2, section 2.2.1. It's about a commerce application. The use case is about getting discounted products for the authenticated user with a "GetFeaturedProducts" method. The use case requires deciding wether the user is a preferred customer and apply discounts accordingly. The author shows a ProductService class (the more or less DDD equivalent of the interactor if I'm getting it right) which calls a repository to retrieve the featured products.

  • The ProductService class requires a ProductRepository as a dependency by constructor injection.
  • The GetFeaturedProducts of the service class requires a User object by method injection (actually, an IPrincipal .NET interface but that's a detail).
  • The service class retrieves the featured products, and then filters the result using the ApplyDiscountFor method of the Product entity.
  • The ApplyDiscountFor method requires a User object and returns a collection of DiscountedProduct objects, which inherit from Product.
  • The result from the GetFeaturedProducts from the service class is a collection of DiscountedProduct objects.
In this example, access is handled by the entity because it's a business rule.

Now, in the context of Entity-Boundary-Interactor a.k.a. Clean Architecture, I'd have the interactor require the User object by constructor injection, and probably have the interactor implement the Command pattern, as in Uncle Bob's PayRoll example.,The interactor itself would correspond to the ProductService class' GetFeaturedProducts method: "GetFeaturedProductsInteractor" or something like that. The rest would be similar.

Sebastian Gozin

unread,
Jun 20, 2013, 5:33:44 AM6/20/13
to clean-code...@googlegroups.com
I initially started out with injecting a SecurityPass or even a Validator object into my interactors which I would then use to detect security/input violations and raise messages back up to the caller.
However I eventually got fed up having to write the same kind of code in every interactor so more recently I've been writing pure happy case interactors but wrapped them inside security and validation interactors which on success simply delegate down to continue processing and in case of violations once again raise messages up to the caller.

In hindsight this seems similar to how these concerns work in existing frameworks such as spring-security or even apache-shiro (I'm actually using this one behind my SecurityPass abstraction).

So far it doesn't feel natural to me to push these rules down into entities because I feel they can be context sensitive. By this I mean 2 different usecases (interactors) could work on the same entity but have different conditions for execution.
I'm definitely still exploring and learning on this topic and wondering if maybe I could push validation down to the entities but I'm not sure.

- Sebastian

Uncle Bob

unread,
Jun 21, 2013, 8:36:04 AM6/21/13
to clean-code...@googlegroups.com
Security is an application specific concern, it belongs to the interactors.  The controllers would access the current user's credentials and pass that information to the interactors.  The interactors would use an authorization service to ensure that their particular interaction was authorized.  The business objects wouldn't know anything about it.  
Reply all
Reply to author
Forward
0 new messages