How to handle user permissions / ACL ?

391 views
Skip to first unread message

Georgef

unread,
Sep 18, 2013, 6:22:30 AM9/18/13
to clean-code...@googlegroups.com
This is the scenario:

A have a user which can have 1..n roles, each role can have 1..n permissions.
Permissions like 'can_read_article', 'can_edit_article', etc...

Where do I handle the authorization process for my user.

So the delivery layer passes along the user credentials and the permissions to the application. From there which part of the application should check whether the user has authorization to perform that interaction?

Ben Biddington

unread,
Sep 18, 2013, 6:25:41 AM9/18/13
to clean-code...@googlegroups.com

User knows its roles, can you ask it? What would the question be?

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at http://groups.google.com/group/clean-code-discussion.

Georgef

unread,
Sep 18, 2013, 6:37:12 AM9/18/13
to clean-code...@googlegroups.com
The User can know about it's roles/permissions... my problem is whether this should be handled by the interactor or entity?

It doesn't seem right that the interactor should authorize the user and decide whether to execute the action or not...



On Wednesday, September 18, 2013 1:25:41 PM UTC+3, Ben Biddington wrote:

User knows its roles, can you ask it? What would the question be?

On 18/09/2013 10:22 PM, "Georgef" <feke...@gmail.com> wrote:
This is the scenario:

A have a user which can have 1..n roles, each role can have 1..n permissions.
Permissions like 'can_read_article', 'can_edit_article', etc...

Where do I handle the authorization process for my user.

So the delivery layer passes along the user credentials and the permissions to the application. From there which part of the application should check whether the user has authorization to perform that interaction?

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.

Roberto Guerra

unread,
Sep 18, 2013, 9:22:58 AM9/18/13
to clean-code...@googlegroups.com
I would add Auth to its own Bounded Context. It could be just a small module that deals with auth that abstracts the underlying libraries. Something like Authorizer probably. This would sit between the controller and the core domain. 

Example:
Lets say we are building a collaboration suite, that includes a ticket system. A user can create a ticket and other users can comment on it. There might be some 'supevisors' that can close the ticket. So we would have a couple roles: 'Supervisor', 'Author', 'Collaborator', for arguments sake. When a requests comes through the controller to close a ticket, the controller would delegate to the 'Authorizer' and only if the role is 'Author' or 'Supervisor' will the rest of the request be delegated to the corresponding core logic, which could be an interactor. The core logic shouldn't really be concerned about permissions, it should only close a ticket. 

Andrew Coulton

unread,
Sep 18, 2013, 4:46:12 PM9/18/13
to clean-code...@googlegroups.com
I think it depends on the complexity of the authorisation system and how central it is to the business logic of the application.

Even in your example, the author will be different for each ticket requested via the controller. There may be more complex rules down the line - for example comments other than by a supervisor might be blocked if the ticket has been closed with a "wontfix" status, or there might be different supervisors depending on the category the ticket has been placed in. There might even be different rules depending on which fields in a ticket are to be updated, requiring the controller to identify changed values rather than just passing the desired final values on to the interactor for processing. I've found those kinds of business rules - related to the identity of the user, the identity of a business entity and aspects of the business entity's state - are quite common.

If authorisation sits entirely between the controller and the interactor, it seems to me that either:
  • the controller has to be able to identify enough information about the entity being requested to establish the relevant permissions - potentially including loading it from the storage layer
  • the interactors responsible for creating or updating an entity have to grant permissions on entities to users via some sort of abstract ACL or similar implementation which is then used by the controller
Neither of these feel quite right to me.

For any non-trivial application, I would lean to encapsulating access control logic in a service layer (or a collection of specific access control policy classes).

  • The controller is responsible for identifying the user, which it may do by caching the result of a "User logs in" use case in a session, by verifying credentials in its own right, or whatever makes sense. It creates the appropriate authorization service/policy with the user identity and injects this service into the interactor.
  • The service exposes a simple API to the interactor, with methods that accept any business entities or specific details that are required for a particular authorization decision and that return TRUE or throw an exception.
  • At whatever point suits the logic of the use case, once sufficient information is available to identify the entity and the permissions required, the interactor asks for an authorization decision.
This allows both the authorization service and interactors to be easily tested with mock objects, and for reuse of access policies across multiple use cases where this is appropriate.

featurefabrik

unread,
Sep 19, 2013, 3:27:28 AM9/19/13
to clean-code...@googlegroups.com
Can't we just call this Auth-Module another use case? Like AuthorizeUser?

I did it in the same way in a recent application, but that introduced an architectural smell (at least, to my specific nose :) ). The information about the roles and what they are allowed to do lays now in the delivery layer. I am not really sure if this is a good or a bad thing. On the positive side you could say it is a good thing, that the core business application is not concerned about any trivial stuff like authentication. But on the contrary side you could say it is not a good idea to decouple a central feature (at least to the customer or the user a very important thing) like that totally from the application logic.

I am somewhere trapped between these two statements. To me they both have valid arguments and I am not able to identify other factors that can be used to determine the architectural way to go.

I am starting to think that both approaches are valid in dependence on the specific kind of application. In really trivial applications (admins can close tickets, users not) it could be the right decision to just validate it by an authentication use case in the delivery tier. Nobody gets hurt, if you encapsulate it this way.
But if we approach more complex applications with different levels of roles and permissions, it could be dangerous to decouple it this way.

It is interesting, that this kind of question arises quite often on this board in different shapes. There is obviously some need for clarification or a handful of best practices that can be used as a guideline for making decisions like that.

I am interested in your insights about this partitioning problem. :)

Sebastian Gozin

unread,
Sep 19, 2013, 4:29:26 AM9/19/13
to clean-code...@googlegroups.com
Something I tend to do is to have a partial usecase/interactor which will check if a user has been authenticated. If not, then it will respond upstream with an unauthenticated message and otherwise it will delegate further processing to a pluggable usecase.

So, in the delivery layer I expect a usecase dependency which I can simply execute. So I inject the composed partial auth and actual usecases and the delivery layer doesn't actually know it is a composed usecase. It just handles the sum of responses.
I then tend to reuse this auth checking usecase with other usecases which also need auth checking.

I think this allows auth to exist in the application layer and not in the transport layer. That is, an API can exist and be used to decide strategy in the application layer. The actual implementation of how to query the current auth session status will probably exist in the transport layer.

Roberto Guerra

unread,
Sep 19, 2013, 6:20:38 AM9/19/13
to clean-code...@googlegroups.com
The specific example I gave was extracted from the book 'Implementing DDD' http://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577 
Moving Auth to its own Bounded Context actually makes it suitable for more complex applications. You can modify the underlying Auth module quite easily this way. If you discover you made a mistake defining the Authorization roles, you just need to fix it in one location. I'd recommend reading Implementing DDD, or Eric Evans' book on DDD.

Uncle Bob

unread,
Sep 23, 2013, 11:53:39 AM9/23/13
to clean-code...@googlegroups.com
One way that I've dealt with this is to have each use case (interactor) know what permissions it requires.  The controller passes the user's permissions in the Request data structure, and the interactor checks that those permissions match (or exceed) the required permissions.
Reply all
Reply to author
Forward
0 new messages