CodamAIDocs
Topicdone

Grant a role

Who may grant? The platform administrator always, everyone else only with delegation, within the ceiling and in the same tenant. The flow with all rejections.

Variants
Platform administratorTenant administrator with delegationwithout delegation → 403above the ceiling → 403other tenant → 403tenant without organization → rejected

What this is about

Granting a role means: a person gets a permission, usually in a specific tenant. For this, CIAS stores a grant and enters the role in Keycloak. With the next token, the person has the role.

Before that happens, CIAS checks whether the caller is allowed to do this at all.

The call

Request
POST /cias/admin/role-assignments
Authorization: Bearer <token of Anna, tenant-admin in nordbau>
{
  "userId": "5c9e…",
  "roleClient": "cias-backend",
  "roleKey": "tenant-user",
  "tenantKey": "nordbau",
  "validFrom": null,
  "validUntil": null,
  "reason": "new colleague in purchasing"
}
Response
HTTP 200
{
  "id": "a41f…",
  "userId": "5c9e…",
  "roleClient": "cias-backend",
  "roleKey": "tenant-user",
  "scope": "TENANT",
  "tenantKey": "nordbau",
  "validFrom": null,
  "validUntil": null,
  "state": "ACTIVE",
  "grantedBy": "nordbau",
  "reason": "new colleague in purchasing"
}
FieldMeaning
userIdthe ID of the user record in CIAS, not the Keycloak sub
roleClient, roleKeythe role, as in the catalog. Empty client = realm role
tenantKeyrequired for a tenant role, forbidden for a platform role
validFrom, validUntiloptional, see Time-limited roles
reasonwhy, for the audit

The checks in order

May this caller grant this role here?
  1. CIAS
    Role
    Does the role exist in the catalog, and is it not retired?
    ↳ no 404 cias.authorization.role-not-found or 409 cias.authorization.role-deprecated
  2. CIAS
    Signed in
    Does the request have a valid token?
    ↳ no 403
  3. CIAS
    Platform administrator?
    yes → all further permission checks are skipped
  4. CIAS
    Tenant role
    Does the role have the scope TENANT? Platform roles are never delegated
    ↳ no 403
  5. CIAS
    Delegation
    Is one of the caller's roles in assignableBy?
    ↳ no 403
  6. CIAS
    Own tenant
    Is tenantKey the tenant from the caller's token?
    ↳ no 403
  7. CIAS
    Ceiling
    Does the caller hold the role themselves, in this tenant or globally?
    ↳ no 403
  8. Grant allowed

After that, CIAS also checks the receiving person and the tenant:

  • A client role with scope PLATFORM for a person whose home tenant has an organization: 403. The role would be in the token, but no request would read it, see Realm role, client role, organization role.
  • A tenant role in a tenant without an organization, that is, a static tenant: 403. In Keycloak, a tenant role is attached to the organization. CIAS never falls back to a global grant, because that would turn a tenant role into a platform role by accident.

All refusals of the permission check look the same: 403 cias.authorization.denied with the text not permitted. CIAS writes the exact reason to the log.

The decision table

Who may grant a role?
CallerScope of the roledelegated to one of the caller's rolesTenant of the grantCaller holds the role thereResult
Platform administrator––––allowed
someone elsePLATFORM–––403
someone elseTENANTno––403
someone elseTENANTyesa different one than their own–403
someone elseTENANTyestheir ownno403, the ceiling applies
someone elseTENANTyestheir ownyesallowed

The own tenant comes from the caller’s token, never from the request. Otherwise every tenant administrator could grant a delegated role in any other tenant. How the ceiling is counted is described in The ceiling: nobody grants more than they have.

The flow when everything is right

sequenceDiagram
    participant A as Anna (tenant-admin)
    participant C as CIAS
    participant DB as CIAS database
    participant K as Keycloak
    A->>C: POST /cias/admin/role-assignments
    C->>C: check role, delegation, tenant, ceiling
    C->>DB: is there already a running grant? otherwise store (ACTIVE)
    C->>K: person into group cias-backend:tenant-user of organization nordbau
    C-->>A: 200 with the grant, event Granted

First store the grant, then Keycloak. If Keycloak fails, CIAS records more than the token carries. That tends to refuse rather than allow too much, and a second call catches up.

The call can be repeated safely: if there is already a running grant for this person, this role and this tenant, CIAS does not create a second one. Two running grants of one role would have two end dates, and nobody would know which one applies. With the same window and reason CIAS returns the existing one; with a different one the existing grant takes it over, see Time-limited roles.

How the role is entered in Keycloak depends on level and scope, see Realm role, client role, organization role.

Variants

Who grants what

When: The token carries a role that the installation counts as platform administrator, in the standalone CIAS platform-admin.

Delegation, own tenant and ceiling are skipped. A platform administrator holds every permission, so they meet the ceiling instead of being exempt from it.

Result: Any role that is not retired, in any tenant or globally.

When: Anna has tenant-admin in nordbau and grants tenant-user in nordbau.

In the standalone CIAS, tenant-user is delegated to tenant-admin. Anna holds tenant-user in nordbau too.

Result: allowed

When: Anna has tenant-owner and tenant-admin in nordbau and grants tenant-admin to Ben.

tenant-admin is delegated to tenant-owner, and Anna holds tenant-admin herself.

Result: allowed

When: Ben has tenant-admin but not tenant-owner and wants to pass on tenant-admin. Or somebody in the tenant wants to grant tenant-owner.

tenant-admin is only delegated to tenant-owner and platform-admin, tenant-owner only to platform-admin.

Result: 403

When: A role is delegated to tenant-admin, but Anna does not hold it.

Delegation says who may pass a role on, the ceiling says how much. Both have to agree.

Result: 403

When: Anna grants tenant-user with tenantKey: suedlogistik.

Anna's token names nordbau.

Result: 403

When: A tenant role is to be granted in the static tenant stadtwerke-nord.

Without an organization, there is no place for a tenant role in Keycloak.

Result: 403, even for a platform administrator

Viewing grants

CallReturns
GET /cias/admin/role-assignments?userId=…all grants of a person, including ended ones
GET /cias/admin/tenants/{tenantKey}/role-assignmentsall grants in a tenant
GET /cias/admin/roles/assignablethe roles you may grant in principle, without retired ones

Pitfalls

Next

Sources in the code and the knowledge base
  • CIAS/cias-authorization – RoleAssignmentService (grant, authorize, refuseAnInvisibleGlobalGrant, pushGrant, organization), ConferralCeiling (mayConfer, heldBy), RoleAssignment.grant, GrantRoleCommand
  • CIAS/cias-authorization – RoleAdminController (POST /cias/admin/role-assignments, GET /cias/admin/role-assignments, GET /cias/admin/tenants/{tenantKey}/role-assignments), AuthorizationRestDtos.GrantRequest, AuthorizationExceptionHandler, RoleAssignmentView, AuthorizationEvent.Granted
  • CIAS/cias-registration – RegistrationService.grantRoles (initial roles directly in Keycloak)
  • CIAS/cias-runtime – CiasPlatformAdministratorConfiguration, CiasDeclaredRoleDelegationConfiguration
  • CIAS/cias-authorization/docs/adr – ADR-018, ADR-023, ADR-031, ADR-043
Search