Architecture ideas on multi-tenancy at customer permisses

Hi,

I’m trying to figure out the best approach for our current scenario:

  1. Our product is made of a Java client (which can and do embed a web browser), and some server applications (not entire monolith but almost)

  2. Our product is deployed on our customer permisses, where customers manage the entire product
    2.1. Therefor the simplest it is for them to manage the full instalation the better the solution is accepted
    2.2. Not all customer allow us to help administrate the productive systems

  3. Some of our customers have users that belong to different “organizations trees”
    3.1. These organization trees are separated entities, not necessarily knowing about each other
    3.2. It’s possible that a small share of the users will belong to both organizations, and on each of them they might have different permissions
    3.3. On such scenario the user needs to choose during the login flow what is the organization where they wish to login
    3.4. These multi-organization users must have a single account (same username / password) across all organizations, specially if the product is connected to a LDAP

  4. The management of users is still done through our already existent screens at our Java application using the Keycloak admin APIs
    4.1 With this we try to simplify the transition within our customers so that they don’t have to use keycloak directly

  5. The growing number of server applications (OIDC resource servers) is increasing, and expected to increase further on next releases

  6. The product is moving to the cloud where some customers will use it, with different installations, and we will manage it for them

We are trying to find the best architecture to support OIDC in this product. For now we are debating what would be the best approach regarding the multi-organization problem:

  1. Use multi-realm, where:
    1.1. each user exists on each realm, and therefor can have different roles
    1.2. Eventually use user federation to support LDAP users
    1.3. If no LDAP is provided by the customer then use identity delegation to a third realm where the user is managed
    1.4. Keycloak client configuration is duplicated in each realm
    1.5. Each realm would map (by name or code, etc) to each organization tree

  2. Use single-realm, where:
    2.1. Organizations are mapped into groups
    2.2. Keycloak client configuration exist only once per customer

Under these 2 approaches we see different advantages & disadvantages:

  1. Advantages of multi-realm:
    1.1. Easy management of different user roles, even if the same user account for each organization

  2. Disadvantage of multi-realm:
    2.1. Much more complex to release configuration changes on further releases, as we don’t know upfront how many realms exists in each customer installation.
    2.2. Much more complex integration between our product Java client and Keycloak, as user management changes might imply making changes to multiple realms, or trigger the user synchronization

  3. Advantages of single-realm (with groups):
    3.1. Predictable configuration at customer installations
    3.2. No duplication of Keycloak client configurations

  4. Disadvantages of single-realm (with groups):
    4.1. We don’t see an easy solution to have different roles per organization
    4.2. Information would be duplicated in our product and Keycloak in attributes or groups… it’s more probable of getting out-of-sync

Questions:

  • Any thoughts on the best approach given these requirements?
  • When a realm is imported does it ignore the groups, or can we make it ignore?
  • Is there any way to deploy / rollout configuration changes (differences instead of full import & overwrite?)
  • Would it be possible, or is there any example, on how to federate another Keycloak realm (similar to LDAP)?

I trully appreciate any help that could be provided, as we’re mostly only finding examples / articles about “simple” deployments self-maintained on the cloud (classical SaaS installations).

Hello,

To answer you question:

When a realm is imported does it ignore the groups, or can we make it ignore?

Check Export and Import
There stands the following:

-Dkeycloak.migration.strategy

This property is used during import. It can be used to specify how to proceed if a realm with same name already exists in the database where you are going to import data. Possible values are:

   IGNORE_EXISTING - Ignore importing if a realm of this name already exists.

   OVERWRITE_EXISTING - Remove existing realm and import it again with new data from the JSON file. If you want to fully migrate one environment to another and ensure that the new environment will contain the same data as the old one, you can specify this.

I don’t have answer for you, we’re at the same point to make the decision. We’re SaaS only. It seems that we are going to try tenant=realm. Having multi-tenants in one realm requires to workaround tenants separation, similar to what you mentioned (having tenant as a group), having different roles will require some naming convention, policies should be written differently. If at some point you’d like to allow your users to add custom policies, it could be very problematic since then they potentially might break the tenants “borders”. Note that there’re multiple articles that mention degradation as more realms are added. We’re going to test it. I noticed that there’re caches per realm and that what might causes the degradation (due to cache fragmentation)

I woud suggest, in a SaaS environment, to go with multi-realm solution. I assume your operations will still maintain the Keycloak server and would somehow have some know-how on it.
just for the sake of discussing the possibilities, if we use the tenants as a group tree, we would probably have a leaf-group per each user, and attach the roles to such groups instead of the user themselfs.
This would avoid the naming convention, and roles could then be given globally (at the user) or by tenant (at the group).

In our case we have multiple customers, which would be realms on a SaaS installation, and then each customer can have it’s own tenants, which we are now inclined on using groups to solve it.

We are now investigating how we could roll-out keycloak configuration changes in such scenario (ex: by a java script with the admin API, or Keycloak CLI), since re-importing the realm would overwrite the groups. We do accept ideas / experiences on this area

Thanks for sharing your thoughts

How did your testing come along?

I moved to another project and keycloack evaluation was frozen, mainly due to the upgrade which doesnt support “live” upgrade and rollback.

@joao-rebelo , I have a similar requirement in development of a SaaS system using keycloak and I would like to share/discuss how we intent to go:

In my scenario users must have a single account and may belongs to many organizations as he was invited.
Also this user can have different access level in organizations (e.g. he can be admin on orgA and common-user in orgB).

At this moment we are using group approach to segregate tenants space. For roles and permissions we are using groups too, where each access level represents a subgroup of top level organization group. Since roles are given in realm and client level only, manage a lot of same roles with org prefix to give access level, we control through sub groups. So instead of use RBAC to control authZ, we decided to go to a GBAC approach in a single realm with top level groups being tenants.

SaaS-Realm
|--org-1 (group)
|--|--admins (group)
|--|--some-role (group)
|--|--another-role (group)
|...
|--org-n (group)
|--|--admins (group)
|--|--some-role (group)
|--|--another-role (group)

The approach you are taking is a common one. The complexity comes with managing all the groups programmatically, but it will work for the use case described.

Also, I have an extension which achieves this by making “Organizations” first-class entities, and then adding membership and roles as children of the orgs:

Let me know if you try that out and need any help.

great! I didn’t know about this extension. I’ll check and discuss with my colleagues. Thanks!