We are investigating Keycloak as a future IAM solution to replace an in-house developed one. we would love some input on best practices and get your thoughts on our proposed setup:
Existing setup
Our product lives on a few domains with multiple tenants, a tenant has their documents, and users have different roles to work with them.
Documents belong to a tenant
Users belong to a domain
Domains have a default tenant
Domains can have more than one tenant
Users have a role on a tenant
So for instance we have app1.our-company.com where we have tenantA and tenantB where I can access and work with their documents based on my roles, as well as app2.our-company.com where we only have tenantC, etc. Some of our apps share a common backend API, and some have an app specific backend API.
The main open point for us is how we deal with the tenant scoped roles and how we can put this information in the access token to be used across all our backend APIs. So in an ideal world we would get an access token like
Then on each of our frontend clients and backend APIs can check exactly what access the user has.
Proposed solution
Single keycloak realm
Users no longer belong to a domain (single identity in the new Keycloak realm)
All our frontend apps get a public client in keycloak where the users can get a token which can be used with all our backend APIs (if the user has access of course!)
Tenant and role mapping represented as groups and subgroups - we then create a protocol mapper to put a list of the group paths in the access token, the groups do not have any roles attached, instead we use the path.
That last point is what we are currently not completely sure about. We would use the group path as a representation of the tenant and role mapping, so a user will have instead of the above:
Is this a common practice or is this something discouraged? We would be open to any suggestions for alternative approaches. I am aware that the preview organizations feature has some multi-tenancy features but this seems geared more towards users that only belong to a single organization, so I think this is not something we can use at the moment.
I wouldnât overload Roles. Roles should transcend tenants. For example, both an admin from Tenant A and an admin from Tenant B should be able to add a new user to the system.
I would use Groups which aggregate your users by Tenant. Membership is set at the user level (group assignment). Youâll use a Mapper to put this in the token. Then your application can use the tenant for need-to-know. (Tenant A cannot add a user for Tenant B).
I thought about something like this where we keep the roles and tenant groups separated but I believe I will run in to issues as we need to be able to have different roles for the same user on different tenants.
So for instance userA has access to tenantA and tenantB data in our application but only read access to A but full access to B. I donât think I can achieve this when without the subgroups as roles approach or am I off?
I had a look at the new organizations feature, but I think that is a no-go for us as the documentation mentions a user can only be linked to a single organization, but we definitely need the option of users having access to more than one tenant: Server Administration Guide
(Iâm definitely going to check out the organizations feature.)
For the matrix of groups and roles from the OP, I would involve the application and have it maintain privileges outside of Keycloak. In the app in front of me there are many groups and nearly 1500 privileges. I donât stuff all that in the token.
Instead, I use coarse-grained roles. For instance, an admin role that might range over all the tenants versus a general user role. This â along with the group â form a URL security scheme.
Then, the app picks up with the specific access granted to it. In the case of ânotesâ, youâll need to check whether someone assigned the user to the read or write privilege for that tenant. Take group and preferred_username to build the vector of privileges.
Itâs free unless youâre reselling it with Keycloak. We did that because we had some Keycloak hosting providers and âdigital transformationâ companies reselling our extensions (and in some cases passing it off as their own work).
We came to the same conclusion with the course roles in the tokens and having each app manage its role â privilege mapping. However in the scheme you suggest I think we can not have a user be an admin of one tenant but only a user on another so which we need in some edge cases.
Yeah I was thinking of simple Roles like admin â which would range over all tenants â and user. âtenant-adminâ would be a privilege. A privilege key is a Group (âtenantâ) and a User and maintained by your app. Ex, I grant Carl tenant-admin for Tenant A.
I donât know why I remember you mentioning the restriction to a single organization. Here is the merged pull request about allowing multiple organizations. Therefore, this feature will be available soon in KC.
Instead of assigning user_1 the roles: backend_dev, frontend_dev
I would just assign the user to the group fullstack_dev that contains the two roles inside it.