I am new to the Keycloak framework and after writing my own solution painfully we are hoping to convert to KeyCloak. It seems to be a promising solution but unfortunately lacking self describing documentation. I have gone through the tutorials and the terminology, however, I can not seem to mold a suitable model for my authorization use case through Keycloak concepts. I posted my question! in Keycloak mailing list without any response so I decided to reach out here.
Please consider this use scenario:
You provide a SaaS solution for Car Dealerships.
Every dealership inherits a set of default roles upon creation e.g. admin, manager, sales, accountant,..)
Dealership could add/remove permissions to the default roles.
Dealership can define their own custom roles.
A dealership has multiple vendors and each vendor has a couple of roles (admin, accountant, vendor)
A dealership has numerous departments and each department may have their own roles for that department.
Basically you have different roles in different contexts.
In my built-in model, I have a table that connects a Role to a Principal (an entity) and the ACLs (or permissions) are assigned to the roles. The Principal could be any of "DealershipA", "DealershipB", "Vendor1" "Department0".
Now my questions is: What is the best practice to implement this scenario in Keycloak.
How would you add/assign a role to an entity?
Would you consider a Dealership, Vendor or a Department a Resource?
Thank you in advance for all your help,
IIUC this scenario could be achieved with different approaches, based on the level of KeyCloak integration you want to do. Let me try to articulate one such way. This could most probably be suboptimal, however you could probably use it as a starting point.
As a start, the Dealership could be considered as a tenant separator, so users in a single Dealership could be gathered to a KeyCloak Realm 1. A Realm groups users together and it sounds like a Dealership is a such separator (if users are indeed allowed to have access to different Dealerships through the same user profile, then this separation cannot be applied).
On to Roles, in one approach each Dealership, Vendor, Department role (admin, sales, acct etc) could be a Realm Role 2. These are Roles available to users in a specific Dealership. However I can't think of a KeyCloak native way to differentiate between Dealership roles vs Vendor roles vs Department roles. These could be differentiated through a naming standard perhaps (ex: vendor-admin)?
In another approach, each entity (Dealership, Vendor, Department) could also be a Group with own attributes and Roles [3]. One advantage could be that the relationship between the entities could be replicated in Group-Subgroup relationship.
sample-group-hierarchy
attributes-of-a-dept-group
This could give you a start on modeling the entities inside KeyCloak.
In authorization, it looks like you will be able to use the Authorization Services available in KeyCloak [4]. I haven't personally used this feature but if you want to rely on KeyCloak as the PAP, PDP and the PEP [5] this looks like the way to go.
For an example, users can be granted or denied access to resources on a specific vendor or department, since user information contains the user's group relationship. This seems like something achievable with a Group based Policy [6].
To give a more direct answer to the questions,
User creation process should make sure proper Role and (or) Group associations are made
Resources seem to be the services offered by each entity type (ex: add_vendor(), view_accounts())
Hope this helps to get a design going. Since most details are not clear at this moment, the design will have to be redone based on future requirements, but at least with a model to validate against you will be able to do it better.
1 - https://www.keycloak.org/docs/6.0/server_admin/#core-concepts-and-terms#realms
2 - https://www.keycloak.org/docs/6.0/server_admin/#realm-roles
[3] - https://www.keycloak.org/docs/6.0/server_admin/#groups
[4] - https://www.keycloak.org/docs/5.0/authorization_services/
[5] - https://www.keycloak.org/docs/5.0/authorization_services/#_overview_architecture
[6] - https://www.keycloak.org/docs/5.0/authorization_services/#_policy_group
Example:
I have two bounded contexts Exams and Courses. The Exams context has a Student entity that has information about the students to take an exam. And the Courses context has a teachers entity that contains information about the teacher teaching a course.
I also have an AuthService (purely CRUD), that is used for Authentication and Authorisation of users. The AuthService has an Accounts entity, which contains information like accounts user's name, address, phone number e.t.c.
Bringing them all together, The Student and the Teacher both have Accounts hence their information is already available.
I have a couple of question about this.
Is it anti-pattern in DDD to store the AccountId in the Student and Teachers Entity? If it isn't anti-pattern at what point is it ok to collect students account information using the AccountId, In repository or in the API controller, or should we use RPC/API calls.
Is it okay to copy the details needed from the Account entity into a Student or Teacher Entity?
I assume the AuthService is in its designated bounded context for authentication and, Accounts is in that same bounded context too.
Here are my answers:
Is it anti-pattern in DDD to store the AccountId in the Student and
Teachers Entity?
You can store AccountId in Student and Teachers entities. This is not an anti-pattern but rather opposite - this is how different aggregates refer to each other, by keeping the Id of the other aggregates.
If it isn't anti-pattern at what point is it ok to
collect students account information using the AccountId, In
repository or in the API controller, or should we use RPC/API calls.
I don't understand which repository you mean exactly, for Account, Student, or Teacher? Each aggregate root has its own repository and that repository is responsible for storing those aggregates only. It does not know or query other aggregates. If you need to query other bounded contexts, do that from the application layer - if the operation that does this is not a domain concern. If it's a domain concern, then do this in the domain layer by representing another bounded context as a domain service (interface). RPC/API is an implementation detail for the inter-bonded context calls and you can use either way to query another bounded context, as long as the implementation details don't leak into the domain layers.
Is it okay to copy the details needed from the Account entity into a Student or Teacher Entity?
That is also okay. You do that to achieve higher availability for the price of eventual consistency. In such a case, the bounded context/entity that holds information from another one acknowledges that the copy of the data can go stale but that is acceptable by the business terms.
Let me know if any questions. I am a long-run DDD practitioner.
I think you are in the wrong way. Something that is related to Authentication should not to be in the domain layer. Student and Teacher are entity, but Account in AuthService is not entity. As far as I see, you would like to add a new Student or Teacher by using some information that come from Account, but for doing that you should pass this information by fetching User Account info and pass them to Student or Teacher class to instantiate a new object.
For your second question, depends on our business, you could have same properties. DDD just emphasize that you should use ubiquitous language for naming entities and methods and it doesn't matter you use same properties.
I'm developing custom security scheme for web application based on Apache Jackrabbit. I've extended standard Jackrabbit security implementation for my needs, and so far it's working correctly. But, I'm having problems with multiple principals being assigned permissions on a node.
For example, user U is a member of group G. Groups G has no read permissions on a node, but user U has read permissions. What I mean by this is, group G has jcr:read privilege set to deny, and user U has jcr:read set to allow on a node.
Based on this, I would assume that user U would be able to read the node, even if he is a member of a group which is not allowed to read. However, the node does not show up for a user U (not expected), or for any other member of group G (expected).
Could somebody help me shed some light on this? Is my assumption correct, or does Jackrabbit calculate actual permissions differently? Or is this just an error in my security implementation?
From this article :
The list of access rights applicable for the subject is constructed from:
- the rights that you assign directly to the user account
- plus all rights assigned to any of the groups that the user belongs to
Means that, Jackrabbit take group privilege instead of user's privilege. You can read the entire article, it is good for JackRabbit secutiry.
Our application uses multiple ways for authorizing access to a given resource. Although it's working, it's messy and... well, it doesn't seem right.
1) Role-based authorization
We have well defined roles where each role has access to a set of the resources and different roles can access the same resources.
Resources, as of now, are simply MVC actions mapped in a database table as module, controller and action.
This seems to be OK, but every time I need to add a new controller/action I have to map this resource to the database table.
2) User-based authorization
Besides role-based authorization, users can have more or less access to a subset of resources of another role. Eg.:
RoleA: resources a, b, c, d
RoleB: resources x, y, z
RoleC: resources 1, 2, 3
User1: has RoleA but needs to access resource y
User2: has RoleB and RoleC but does not have access to resource z
This is implemented as an user_resources table with entries for additional resources that the user has access or is denied (indicated by a flag).
I could create different roles with tailored access, treating roles as group of permissions, but that would lead to a roles explosion.
3) Model state authorization
If that's not enough, some actions can only be performed when the model is in a certain state (each model knows when something can be done). Eg.: an order can only be edited if the user has access to the edit resource (through steps #1 or #2) and the object Order can be edited.
Anoter example: an user can access a Customer if he has access to /customer/view resource and he owns that Customer (he is the contact info for that customer).
4) Display information in UI
A role, group of roles or individual users can see more or less information about a model, depending on it's state.
How can I simplify this authorization process without loosing flexibility in giving or restraining access to resources?
There is any pattern I'm missing here to unify all this authorization in a single place?
After a long time I finally found an answer that satisfies all my requirements:
http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/.
His solution is to consider everything as an activity, the permission to execute/call/whatever an activity is given to a role and users can have multiple roles.
What shines in this approach is that the permission check is done on the activity itself, not on the roles.
I've implemented access control by using the specification pattern, which I find directly suited for this. A central method is isSatisfiedBy. X is allowed to do y if it is satisfied by z. Eg a user is allowed to view 'the admin page' if it is satisfied by 'has admin role'. See how isSatisfiedBy can be very generic (eg 'is user with id 324', 'has been logged in for 30 minutes', 'is member of group foo', ...). Rules then become of the following general form:
allow X to do Y if X satisfies Z
Can anyone tell me, what's the real difference between group and role? I've been trying to figure this out for some time now and the more information I read, the more I get the sense that this is brought up just to confuse people and there is no real difference. Both can do the other's job. I've always used a group to manage users and their access rights.
Recently, I've come across an administration software, where is a bunch of users. Each user can have assigned a module (whole system is split into a few parts called modules ie. Administration module, Survey module, Orders module, Customer module). On top of it, each module have a list of functionalities, that can be allowed or denied for each user. So let's say, a user John Smith can access module Orders and can edit any order, but haven't given a right to delete any of them.
If there was more users with the same competency, I would use a group to manage that. I would aggregate such users into the same group and assign access rights to modules and their functions to the group. All users in the same group would have the same access rights.
Why call it a group and not role? I don't know, I just feel it that way. It seems to me that simply it doesn't really matter :] But I still would like to know the real difference.
Any suggestions why this should be rather called role than group or the other way round?
The divide between role and group comes from concepts of computer security (as opposed to simply resource management). Prof. Ravi Sandhu provides a seminal coverage of the semantic difference between roles and groups.
http://profsandhu.com/workshop/role-group.pdf
A group is a collection of users with a given set of permissions assigned to the group (and transitively, to the users). A role is a collection of permissions, and a user effectively inherits those permissions when he acts under that role.
Typically your group membership remains during the duration of your login. A role, on the other hand, can be activated according to specific conditions. If your current role is 'medical-staff' you might be able to see some of the medical records for a given patient. If, however, your role is also 'physician', you might be able to see additional medical information beyond what a person with just a role of 'medical-staff' can see.
Roles can be activated by time of day, location of access. Roles can also be enhanced/associated with attributes. You might be operating as 'physician', but if you do not have a 'primary physician' attribute or relation with me (a user with 'patient' role), then you cannot see my entirety of medical history.
You could do all that with groups, but again, groups tend to focus on identity, not role or activity. And the type of security aspects just described tend to align themselves better with the later than with the former.
For many cases, for the usage of classifying things together (and nothing more), groups and roles function just the same. Groups, however, are based on identity, whereas roles are meant to demarcate activity. Unfortunately, operating systems tend to blur the distinction, treating roles as groups.
You see a much clearer distinction with application or system-level roles - carrying application or system-specific semantics (like in Oracle roles) - as opposed to 'roles' implemented at the OS level (which are typically synonymous to groups.)
There can be limitations to roles and role-based access control models (like with anything of course):
http://www.lhotka.net/weblog/CommentView,guid,9efcafc7-68a2-4f8f-bc64-66174453adfd.aspx
About a decade ago I saw some research on attribute-based and relationship-based access control which provide much better granularity than role-based access control. Unfortunately, I haven't seen much activity on that realm in years.
The most important difference between roles and groups is that roles typically implement a mandatory access control (MAC) mechanism. You do not get to assign yourself (or others) to roles. A role admin or role engineer does that.
This is superficially similar to UNIX groups where a user can/might be able to assign himself to a group (via sudo of course.) When groups are assigned according to a security engineering process, the distinction blurs a bit, however.
Another important characteristic is that true RBAC models can provide the concept of mutually exclusive roles. In contrast, identity-based groups are additive - a principal's identity is the sum (or conjunction) of the groups.
Another characteristic of a true-RBAC based security model is that elements created for a particular role typically cannot be transitively accessed by someone who does not act under that role.
On the other hand, under a discretionary access control (DAC) model (the default model in Unix), you cannot get that type of guarantee with groups alone. BTW, this is not a limitation of groups or Unix, but a limitation of DAC models based on identity (and transitively, with identity-based groups.)
Hope it helps.
=======================
Adding some more after seeing Simon's well-put response. Roles help you manage permissions. Groups help you manage objects and subjects. Moreover, one could think of roles as 'contexts'. A role 'X' can describe a security context that rule how subject Y access (or does not access) object Z.
Another important distinction (or ideal) is that there is a role engineer, a person that engineers the roles, the contexts, that are necessary and/or evident in an application, system or OS. A role engineer typically is (but does not have to be) also a role admin (or sysadmin). Moreover, the true role (no pun intended) of a role engineer is in the realm of security engineering, not administration.
This is a novel group formalized by RBAC (even if it seldom gets used), one which has typically not been present with group-capable systems.
A group is a means of organising users, whereas a role is usually a means of organising rights.
This can be useful in a number of ways. For example, a set of permissions grouped into a role could be assigned to a set of groups, or a set of users independently of their group.
For example, a CMS might have some permissions like Read post, Create post, Edit post. An Editor role might be able to Read and Edit, but not create (don't know why!). A post might be able to Create and Read etc. A group of managers might have the editor role, while a user in IT, who is not in the managers group, may also have the editor role, even though the rest of his or her group does not.
So while in a simple system groups and roles are often closely aligned, this is not always the case.
A "group" is a collection of users. A "role" is a collection of permissions. That means that when group alpha includes group beta, alpha receives all the users from beta and beta receives all the permissions from alpha. Conversely, you could say role beta includes role alpha and the same conclusions would apply.
A concrete example makes things more clear. Consider "customer support" and "senior customer support". If you think of those collections as groups, then it is clear that customer support users "includes" senior customer support users. However, if you look at them as roles, then it is clear that senior customer support permissions "includes" customer support permissions.
In theory, you could simply have one collection type. However, it would be ambiguous if you were to say that "collection alpha includes collection beta". In that case, you can't tell if the users in alpha are in beta (like a role) or the users in beta are in alpha (like a group). In order to make terminology like "includes" and visual elements like tree views unambiguous, most rbac systems require you to specify whether the collection at issue is a "group" or a "role" at least for the sake of discussion.
Some analogies might help. Framed in terms of set theory, when group alpha is a subset of group beta, then permissions alpha are a superset of permissions beta. Compared to genealogy, if groups are like a tree of descendants, then roles are like a tree of ancestors.
Although there is semantic difference between Roles and Groups (as described above by other answers), technically Roles and Groups seems to be the same.
Nothing prevents you to assign Permissions directly to Users and Groups (this can be considered as a fine-tuning access control).
Equivalently, when User is assigned a Role, it can be considered a role Member, in the same sense when user becomes Member of a Group.
So we can end up with no real difference between Roles and Groups. Both can be considered for grouping Users AND/OR Permissions.
Thus difference is only semantic:
— if it is semantically used for grouping Permissions, it is then a Role;
— if it is semantically used for grouping Users, it is then a Group.
Technically, there is no difference.
NOTE - the following ramblings only makes sense if one is trying to impose security within an organization - that is to say, trying to limit the access to information...
Groups are empirical - they answer the question of "what". They are the "is" in the sense they reflect the existing reality of access. IT people love groups - they are very literal and easy to define. Eventually, all access control ultimately devolves (as we all learned back in middle school...) to answering the question "To what group do you belong?"
Roles, however, are more normative - they guide what "should be". Good managers and HR love "roles" - they don't answer - they ask the question of "Why?" Unfortunately, roles can also be vague and that "fuzziness" can drive (IT) people nuts.
To use the medical example above, if the role of "primary care physician" has more rights (i.e. access to more groups) than the role of an "x-ray technician", this is because people (managers and HR) decided why that needed to happen. In that sense they are "the collective wisdom" of an organization.
Let's say a doctor is given access (membership to a group with access) to financial records of patients. This is normally outside the "role" of a doctor and should be debated. So, no one (no matter how qualified) should have full access to all groups - it invites abuses to power. This is why "role engineering" is so important - without it, you just have group access handed out like so much candy. People will collect (and sometimes horde) group access with no discussion as to the dangers of too much power.
To conclude, the wisdom of well-defined roles helps moderate the dangers of runaway group access. Anyone in an organization can argue for access to a particular group. But once that access is provided, it's rarely given up. Role engineering (along with best-practices like well-defined group descriptions and empowered group access managers) can limit conflicts of interest within an organization, decentralize decision-making and help make security management more rational.
The previous answers are all wonderful. As was stated, the concept of Group vs Role is more conceptual than technical. We have taken the stance that Groups are used for containing users (a user can be in more than one group: i.e. Joe is in the Managers group as well as the IT group [he is a manager in IT]) and for assigning broad privileges (i.e. Our mag card system allows all users in the IT group access to the server room). Roles were used to now add privileges to specific users (i.e. people in the IT group can RDP to servers but cannot assign users or change permissions, people in the IT group with the Admin role can assign users and change permissions). Roles can be made up of other roles as well (Joe has Admin role to add users/privileges and also has DBA role to do database changes to the DBMS on the server). Roles can be very specific as well in that we can make individual user Roles (i.e. JoesRole) that can be very specific for a user. So, to recap, we use Groups to manage users and assign general Roles and Roles to manage privileges. This is also cumulative. The Group the user is in may have Roles assigned (or a list of available Roles) that will give very general privileges (i.e. IT group users have the role ServerRDP that lets them log onto the servers) so that is assigned to the user. Then any Roles the user belongs in will be added in the order they are defined with the last Role having the final say (Roles can Allow, Deny or not apply privileges so that as each Role is applied it will either override previous settings for a privilege or not change it). Once all the Group level Roles and User level Roles have been applied, a distinct security model is created for the user that can be used throughout our systems to determine access and capabilities.
Users are assigned to Roles based on the responsibility they play in any system. For example users in role Sales Manager can perform certain actions such as provide additional discount for a product.
Groups are used to 'group' users or roles in a system for easy management of security. For example a group named "Leadership Group" can have its members from roles Managers, Directors & Architects and individual users who are out of these roles as well. Now you should be able to assign certain privileges to this group.
Purpose of Groups and Roles vary in applications, but mainly what i understood is as follow,
Groups(set of users) are static while Roles(set of permissions) are dynamic with policies, for example based on time from (9 to 6) a group or user may have this role but not that.
You can assign a role to group. You can assign user to group and you can assign role to individual user in any role user. Meaning. Jean Doe can be in Group of SalesDeptartment with role off ReportWritter which allows to print our reports from SharePoint, but in SalesDepartment group, others may not have role of ReportWritter. - In other words, roles are special privileges withing assigned groups. Hope this makes any scenes.
Cheers!!!
This works for us:
Manage user policies through groups (occasionally add additional policies manually to individual users)
Manage service policies through roles (for example a microservice might need access to S3 and it will be granted permissions via a role)