What this is about
Imagine every new colleague in support needs the same ten roles, spread across CDMS, CRMS and the realm. You could grant each role one by one, for every person, and revoke each one again when they leave. Or you create the group support once, give it the ten roles, and make the colleague a member.
So a group is a bundle of roles with members. Whoever is a member gets all roles of the group. Whoever leaves the group loses them again.
The picture
flowchart LR
subgraph C["CIAS (manages the group)"]
direction TB
G["Group support<br/>name, description<br/>default group: no"]
R["Roles<br/>realm: user<br/>cdms-backend: customer-read, order-edit<br/>crms-backend: ticket-edit"]
M["Members<br/>Anna, Ben, Chris …"]
G --> R
G --> M
end
subgraph K["Keycloak (holds the copy)"]
KG["Group support in the realm<br/>cias-managed = true<br/>role mappings, members"]
end
C -- "writes the copy" --> K
K -- "roles of the group" --> T["Token of every member"]
Read it like this: a group bundles roles and has members. CIAS writes both to Keycloak. Keycloak puts the roles of the group into the token of every member, exactly as if the person had received them one by one.
What belongs to a group
| Part | Meaning |
|---|---|
key | the key, for example support. It never changes. In Keycloak the group has exactly this name. At most 128 characters |
name | what people read, for example “Support 1st Level”. If it is missing, CIAS uses the key. Only in CIAS; Keycloak shows the key |
description | what the group is for. In Keycloak it is stored in the attribute description |
roles | the roles the group grants: realm roles and client roles of any number of modules. Each must be in the role catalog |
| members | the people, by the ID of their user record in CIAS |
defaultGroup | whether every new account automatically becomes a member, see The default group |
syncState | whether the copy in Keycloak matches the state in CIAS: SYNCHRONIZED or PENDING, see Reconciliation with Keycloak |
Inside a group, a role is always named by client plus key, because the same key can be two different permissions on two clients. An empty client means: realm role. More on this in Realm role, client role, organization role.
The variants
When: The group carries roles without a client, such as user or allowed-tenant-context-switch.
Realm roles end up in the token under realm_access.roles. They apply in every tenant, whatever its kind.
Result: works everywhere
When: The group carries cdms-backend: customer-read and crms-backend: ticket-edit.
This is exactly what groups are for: a job in a company does not stop at module boundaries. A composite role could not do this, it always lives on one client or in the realm. Client roles from a group end up under resource_access.<client>.roles.
Result: works as long as the tenant of the request carries no roles of its own, see Group roles under dynamic tenants
When: The group is created, the roles come later.
This is allowed. A group without roles gives nobody anything, even if it already has members.
Result: valid, grants nothing
When: defaultGroup is true.
Every account created from now on becomes a member. Anyone who already has an account stays as they are.
Result: see The default group
Platform wide and flat
A group has no tenant. It applies across the whole platform. Anna from nordbau and Ben from suedlogistik can be in the same group. Both get the same roles, but each uses them only on the data of their own tenant. The group does not connect the two. See Tenant, organization, group.
A group also has no subgroups. Every group stands on its own, and a person can be in several groups. If a person has a role through two paths, they simply have it, not twice.
Group, individual grant, grant in the tenant
- many roles at once, across modules
- applies globally, without a tenant
- no end date, no reason per person
- managed only by the platform administrator
- Whoever leaves the group loses all its roles
- a role with scope
PLATFORM - with end date and reason
- visible as a grant in CIAS
- managed by the platform administrator
- a role with scope
TENANT - applies only in this tenant
- with end date and reason
- a tenant administrator with delegation may do it too
Individual grants are covered in Grant a role.
| Do several people need the same bundle of roles? | Should it apply in only one tenant? | Does it need an end date per person? | Use |
|---|---|---|---|
| – | yes | – | a grant in the tenant, no group |
| – | no | yes | an individual grant with validUntil |
| yes | no | no | a group |
| no | no | no | an individual grant; a group is not worth it |
Two systems, one fixed order
Every change to a group writes twice: to the CIAS database and to Keycloak. There is no shared transaction. That is why one fixed rule applies:
| What happens | Order | If it breaks off in between … |
|---|---|---|
| giving something: create a group, add a role, add a member | CIAS first, then Keycloak | … it is in CIAS but not yet in the token. The group is PENDING |
| taking something: remove a role, remove a member, delete a group | Keycloak first, then CIAS | … the permission is already gone, the record is still there |
So after an interruption there is always less permission left, never more. How a leftover PENDING gets caught up is described in Reconciliation with Keycloak.