What this is about
Every registration must know which tenant the person ends up in: a new one, an existing one, or none at all. This is set by the tenant assignment, configured per flow as tenant-assignment.
The six kinds
| Assignment | Meaning | Where the key comes from | Allowed for |
|---|---|---|---|
NONE | no tenant | – | all flows |
CREATE_NEW | new tenant, the person founds it | from the payload, a hook, or derived from company | all flows |
JOIN_EXISTING | join an existing tenant | from the payload or a hook, required | all flows |
FROM_CALLER | the calling person’s tenant | from their token | not SELF_SERVICE, because there is no caller there |
FROM_PAYLOAD | tenant named by the caller | from the tenantKey field | only PLATFORM_ADMIN |
FROM_INVITATION | tenant named when inviting | from the request, required | all flows |
The rules in the last column are built in: if a configuration sets, say, FROM_PAYLOAD for SELF_SERVICE, CIAS rejects registrations in that flow.
The shipped settings
| Flow | Assignment in cias-runtime | Effect |
|---|---|---|
SELF_SERVICE | CREATE_NEW | every self-registration founds a tenant |
TENANT_ADMIN | FROM_CALLER | invitation into your own tenant |
PLATFORM_ADMIN | not configured | see Creation by the platform administrator |
The decision path
-
CIASPolicy
tenant-assignmentof the flow, plus a key from the token or payload -
CIASFROM_CALLER?Then the tenant is fixed. Hooks are not asked at all
-
HookHooks
onResolveTenantmay replace the decision, one after another -
CIASDerive key
CREATE_NEWwithout a key? Then derive it fromcompany - The tenant is fixed and is stored on the registration
This decision is made when the registration is submitted. Whether the tenant exists is checked by CIAS during provisioning. See What happens on completion.
Each kind in detail
When: An installation without tenants, or a flow for people without a company.
The person gets no tenant. A tenantKey in the payload is ignored. The roles come from the TENANTLESS situation.
When: Self-registration of a company.
The key is derived from the company field if neither the payload nor a hook names one: accents removed, lowercase, other characters become -, at most 48 characters. If company is missing, the domain of the address is the source, for example muster-bau from anna@muster-bau.de. If the key is taken, CIAS appends -2 to -20. During provisioning the organization and the tenant are created; the person is the founder (TENANT_FOUNDER).
When: A hook or caller knows which existing tenant the person belongs to.
Without a key this assignment is invalid. The person becomes a member (TENANT_MEMBER).
When: Invitation by a tenant administrator.
The tenant comes from their token. A tenantKey in the payload is discarded, hooks are not asked. If the caller has no tenant: 403.
When: Creation by the platform administrator.
The tenant comes from the tenantKey field. If it is missing: 400.
When: The request names the tenant the person is invited into.
As with JOIN_EXISTING, the person becomes a member of the named tenant. Without a key the assignment is invalid.
When: A project has its own rules, for example: addresses with @nordbau.example always belong to nordbau.
A hook with onResolveTenant gets the policy's decision and returns a new one, or null for “unchanged”. CIAS stores the reason on the registration. With FROM_CALLER the hook is not called.
Result: See Your own logic: hooks and events.