What this is about
A tenant being in the token does not yet mean that it may work. A customer can be suspended, their contract can have expired, or they may not exist at all. That is why the filter chain asks a second question on every request: Is this tenant served?
The place that asks this question is called the tenant gate. CIAS gives the answer, because that is where it is recorded which customers exist and what state they are in. CDMS keeps no list of its own for this.
The gate on the path of the request
-
CIASCheck tokenIs the token valid?↳ no 401
-
CIASDetermine tenantDoes the token name exactly one tenant?↳ no 403
cias.authentication.tenant-unresolvedortenant-required -
CIASTenant gateIs this tenant served?↳ no 403
cias.authentication.tenant-not-served -
CIASTenant switch
tenantheader set and allowed? Then ask the gate again for the target↳ no 403cias.authentication.tenant-not-servedif the target is not served -
CDMSPersistence targetTenant in the list of allowed tenants?↳ no 403
CDMS_TENANT_SWITCH_NOT_AUTHORIZED - Access to the tenant's database
The gate stands in front of CDMS. So it also protects requests that do not touch any database, for example a request that only reads system models.
When a tenant is served
CIAS answers yes when both are true:
- The tenant is in the state active.
- Today’s date lies within its validity period (start and end, both optional, both inclusive).
| Tenant in CIAS | State | today within the validity period | CIAS reachable | Result |
|---|---|---|---|---|
| known | active | yes | yes | served, the request continues |
| known | active | no | yes | 403 tenant-not-served |
| known | being provisioned, suspended or closed | – | yes | 403 tenant-not-served |
| unknown | – | – | yes | 403 tenant-not-served |
| – | – | – | no, but answer remembered | the remembered answer applies, a refusal too |
| – | – | – | no, nothing remembered | 403 tenant-not-served |
All refusals look the same to the client. That is deliberate: if the response revealed whether a tenant exists, anyone with a valid token could query the customer list. You find the exact reason in the CDMS log.
The states and how a tenant moves between them are described in The life cycle of a tenant and Suspending and closing tenants, validity.
The gate remembers answers
The question comes on every request, the answer rarely changes. The gate therefore remembers each answer for a short time, 30 seconds by default. This can be set with codamai.cias.tenant-gate.ttl.
When: The last answer for this tenant is younger than 30 seconds.
The gate takes the remembered answer and does not ask CIAS.
Result: Most requests cost no round trip.
When: No answer remembered, or the remembered one is older.
-
1CIASgate asks CIAS: is
acmeserved? -
2CIASremembers the answer for the next 30 seconds
Result: If CIAS runs in the same application, this is a method call. If CIAS runs as a separate service, an HTTP request.
When: The question fails: timeout, connection error, unreadable response.
-
1CIASgate has a remembered answer, however old → takes it
-
2CIAS→Clientno remembered answer → 403
tenant-not-served
Result: A CIAS outage throws out nobody who was already working, and lets nobody new in.
The details of an outage are in When CIAS is not reachable.
A suspension takes effect with a delay
sequenceDiagram
participant A as Admin
participant CIAS as CIAS
participant G as Tenant gate
participant C as Client of acme
C->>G: Request (0 s)
G->>CIAS: Is acme served?
CIAS-->>G: yes, remembered for 30 s
A->>CIAS: suspend acme (10 s)
C->>G: Request (20 s)
G-->>C: remembered: yes, continues
C->>G: Request (35 s)
G->>CIAS: Is acme served?
CIAS-->>G: no
G-->>C: 403 tenant-not-served
So a suspension takes effect at the latest after the configured time. Choosing a longer time saves round trips, but also extends the time a suspended customer keeps working.
Special cases
When: The tenant header has changed the tenant of the request.
The gate asks a second time, now for the target. A suspended tenant stays suspended for everyone, including administrators who switch into it.
Result: See Tenant switch by header.
When: The token names no tenant.
The gate has no question to ask and lets the request through. In MULTI the filter chain still refuses it because the tenant is missing, see Where the tenant of a request comes from.
Result: The gate does not ask for requests without login either.
When: The tenant in the token is not a valid tenant key, for example with uppercase letters.
The gate treats it like an unknown tenant, without asking CIAS.
Result: 403 tenant-not-served
When: CODAMAI_PERSISTENCE_TENANT_MODE=SINGLE
CIAS determines no tenant, so the gate never asks. A tenant in the token is neither checked nor refused.
Result: See In SINGLE the tenant in the token does not count.
Pitfalls
Where to go next
- The CIAS view: Admitting the tenant (tenant gate)
- Both operating modes side by side: The tenant check in both operating modes
- What happens next in CDMS: Which database? The persistence target