Domain-Driven Design – Implementing Users and Permissions

authorizationdomain-driven-designimplementationspermissions

I am working on a small application trying to grasp the principles of domain-driven design. If successful, this might be a pilot for a larger project. I'm trying to follow the book "Implementing Domain-Driven Design" (by Vaughn Vernon) and trying to implement a similar, simple discussion forum. I've also checked out the IDDD samples on github. I have some difficulties adopting the Identity and Access to my case. Let me give some background information:

  • I (hopefully) understand the reasoning behind separating the users and permissions logic: it is a supporting domain, and it's a different bounded context.

  • In the core domain, there are no users, just Authors, Moderators, etc. These are created by reaching out to the Identity and Access context using a service and then translating the received User objects to and Moderator.

  • Domain operations are called with a related role as a parameter: e.g.:

    ModeratePost( ..., moderator);

  • The method of the domain object checks if the given Moderator instance is not null (the Moderator instance will be null if the user asked from the Identity and Access context does not have the Moderator role).

  • In one case, it does an additional check before altering a Post:

    if (forum.IsModeratedby(moderator))

My questions are:

  • In the latter case aren't the security concerns blended again into the core domain? Previously the books states "with who can post a subject, or under what conditions that is permitted. A Forum just needs to know that an Author is doing that right now".

  • The role based implementation in the book is fairly straightforward: when a Moderator is the core domain tries to convert the current userId into a Moderator instance or into an Author when it needs that. The service will respond with the appropriate instance or a null if the user does not have the required role. However, I can't see how could I adapt this to a more complex security model; our current project I'm piloting for has a rather complex model with groups, ACLs, etc.

Even with rules that are not much very complex, like: "A post should be edited only by its Owner or an Editor", this approach seems to break down, or at least I don't see the correct way to implement it.

By asking the Identity and Access context for an OwnerOrEditor instance doesn't feel right, and I would end up with more and more security-related classes in the core domain. In addition, I would need to pass not just the userId, but the identifier of the protected resource (the id of the post, forum, etc.) to the security context, which probably should not care about these things (is it correct?)

By pulling the permissions to the core domain and checking them in the methods of the domain objects or in the services, I'd end up at square one: mixing security concerns with the domain.

I've read somewhere (and I tend to agree with it) that these permission related things should not be a part of the core domain, unless security and permissions are the core domain itself. Does a simple rule like the one given above justify making security a part of the core domain?

Best Answer

It's sometimes difficult to distinguish between real access control rules and domain invariants borderlining on access control.

Especially, rules that depend on data only available far into the course of a particular piece of domain logic might not easily be extractible out of the domain. Usually, Access Control is called before or after a domain operation is performed but not during.

Vaughn Vernon's assert (forum.IsModeratedBy(moderator)) example probably should have been outside the Domain, but it is not always feasible.

I would need to pass not just the userId, but the identifier of the protected resource (the id of the post, forum, etc.) to the security context, which probably should not care about these things (is it correct?)

If there's a Security BC and you want it to handle that logic, it doesn't have to know what a Forum is in detail but :

  • It could just have knowledge of concepts like "moderated by" and grant or deny access rights accordingly.
  • You could have adapter logic that subscribes to Core Domain events and translates them to simple (resource, authorizedUsers) key value pairs for the Security BC to store and use.