The short answer
I suspect your question stems from wanting to avoid having another context (e.g. the Orders
application layer) depend on the User Access
domain logic.
The direct answer to that part of the question is that it is perfectly okay to do so, because the application of the user access bounded context is inherently intended to be used by the application layer (across all bounded contexts that need user access control).
The longer answer
In most app features you develop, there are two parts of the story. Sorry for being vague but the naming here is a bit fuzzy. I'm going to call these two stages the setup and the application.
In order to disambiguate, I'm going to refer to software applications as "apps". When I say "application", I mean the stage that I just labeled.
The setup is where you prepare your information, not to be used right now but to have it readily available at a later stage. This could be something like:
- A police app which allows you to enter fines/infractions/arrests
- A library app allowing you to enter its book collection into the database
- Defining user access rights for an app's resources
When you get to the application stage, you use your setup in order to achieve the goal you intend to achieve. For the given examples:
- You can review a person's criminal history during e.g. a police stop or a court case
- You are able to check out a book in the app
- You can decide whether the current user is allowed access to a particular app resource
I picked these three examples for a very particular reason. In regards to their setup, it's always the same CRUD principle. Nothing really changes here. But the application stage is notably different in that:
- The police app is a simple data-in-data-out app, and the application of this setup is applied outside of the app (by the end users having access to this data and using it in the real world)
- The library app uses the setup in order to supply a secondary app feature: checking out a book. The application here is applied to the app itself, as part of a public (end user facing) feature.
- The access control uses the setup in order to support its own internal workings. The application here is applied to the app's internal/private logic which the end user is not privy to.
Okay, this was a whole lot of setup, but now comes the application (this pun is totally intended and I dearly apologize if you're groaning):
A bounded context can contain setup, its own application, the application of another bounded context, or any combination of these. There is no One True Answer to your question, because this can vary based on context.
Specifically, in the given examples:
- The criminal records bounded context can logically only contain setup, since the application is not found within the app.
- The books bounded context only contains setup, but there is a second checkout bounded context which contains the application of the books context
- The user access bounded context is only setup, but effectively every bounded context in the app (which requires user access control) contains the application (including the user access bounded context itself, since not every user can set the user access rights)
This brings me to your statement:
In those examples, the User Access bounded context (register, login, authorization...) is considered a generic bounded context and could be a shared kernel.
When dealing with user access, what you're going to find is that you have both a neatly defined bounded context that contains all of the setup; and you're also going to be peppering the entire set of bounded contexts (which require user access control) with references to that user access bounded context (what you call the shared kernel), because that is the application of that setup.
But I can't find the right place to put it in the Clean Architecture/Onion Architecture.
Due to the above conclusion, it's going to live in more than one place. However, each part has its own specific place that it belongs.
It appears in the application layer for authorization.
It appears in the domain layer because... it is a bounded context, duh.
I chose the name "application" for this stage for a really similar reason why people often refer to the "application" layer: it is where you start using (applying) the things that you've built.
In this particular case of user access control, there is a neat split whereby the setup belongs in the domain layer (because it is a CRUD bounded context just like any other) and the application of that setup belongs to the application layer (as it gets used by every bounded context which needs to provide user access control).
I suspect your question stems from wanting to avoid having another context (e.g. the Orders
application layer) depend on the User Access
domain logic. The direct answer to that part of the question is that it is perfectly okay to do so, because the application of the user access bounded context is inherently intended to be used by the application layer (across all bounded contexts that need user access control).
The user could appear in some other bounded contexts, but should not exist in some bounded contexts that do not require the user data
Two things:
- You're going to find that more often than not, the user bounded context and the user access bounded context are two different things. If you are dealing with cases where you want to refer to users without referring to their access, that you're going to need to separate these bounded contexts.
- Obviously, the application of user access control is only needed in bounded contexts whose resources should be access controlled. If some of your app's resources are publicly available, then you simply don't need to reference any user access control. That's perfectly fine.