CodamAIDocs
Topicdone

The user record

Why CIAS keeps its own record next to the Keycloak account, what it contains, and what it never contains.

Variants
Fields of the recordwhat it never containshow a record is createdQueries for administrators

What this is about

Every person has an account in Keycloak: address, password, MFA, sessions. In addition, CIAS keeps its own user record. Why two?

  • Keycloak is responsible for sign-in. What a person is in business terms, which tenant they belong to, and whether they are suspended belongs to CIAS.
  • If everything were only in Keycloak, switching the IdP would mean a data migration of all users.
  • Without its own record, there would be nothing after a registration that CIAS could suspend, list, or assign to a tenant.

Record and account

flowchart LR
    subgraph C["CIAS: cias_user"]
      direction TB
      c1["id (own UUID)"]
      c2["externalUserId"]
      c3["email, displayName"]
      c4["status"]
      c5["homeTenantKey"]
      c6["attributes"]
    end
    subgraph K["Keycloak: account"]
      direction TB
      k1["id (sub in the token)"]
      k2["username = email"]
      k3["password, MFA, sessions"]
      k4["enabled"]
      k5["profile attributes"]
    end
    c2 -- "points to" --> k1
    c4 -. "ACTIVE ↔ enabled" .-> k4

The fields

FieldMeaning
idown ID in CIAS, a UUID. All other CIAS data points to it
externalUserIdthe ID of the account in Keycloak, sub in the token. Unique
emailthe address and also the login. Always stored in lowercase, unique, cannot be changed
displayNamedisplay name. If it is missing, the address is shown
statusPENDING, ACTIVE, SUSPENDED, or CLOSED, see The lifecycle of a user
homeTenantKeythe home tenant, or empty in an installation without tenants
attributesbusiness notes as key-value pairs, see Maintain a person’s attributes

The record lives in the system database, never in a tenant’s database.

The home tenant is one tenant. CIAS does not keep other tenants the person is a member of on the record. They are stored in Keycloak and arrive via the token.

What it never contains

No password, no password hash, no MFA secret, no recovery code, no token. An automated architecture test even prevents anyone from adding a field with such a name. This is why you can safely back up, copy, and read the record in support.

How a record is created

Two ways to a record

When: A registration is completed.

At the end of provisioning, a hook creates the record: address, name from first and last name, tenant from the registration, the other form fields as attributes. Then it sets the record to ACTIVE. If a record already exists for the account, it stays as it is.

Result: See What happens on completion.

When: Keycloak has accounts that CIAS does not know yet.

A platform administrator starts the import. CIAS creates a record for every unknown account.

Result: See Import existing accounts.

There is no endpoint to “create a user by hand”. New people come in through registration.

Queries for administrators

All endpoints are under /cias/admin/users and are for platform administrators only.

CallResult
GET /cias/admin/users/page?query=&page=0&size=50page with items, page, size, total, hasMore. query searches address and display name, case-insensitive
GET /cias/admin/users?tenantKey=nordbauall people with this home tenant, sorted by address. Without tenantKey: all people without a tenant
GET /cias/admin/users/by-email?email=…one person or 404
GET /cias/admin/users/{id}one person
Request
GET /cias/admin/users/3f0c…
Response
{
  "id": "3f0c…",
  "externalUserId": "7f3c…",
  "email": "anna@nordbau.example",
  "displayName": "Anna Berg",
  "status": "ACTIVE",
  "homeTenantKey": "nordbau",
  "attributes": { "department": "Einkauf" }
}

Errors come as { "error": "cias.user.…", "message": "…" }. If the role is missing, CIAS responds with 403 cias.user.administration-denied, no matter whether the person exists. An unknown ID results in 404 cias.user.not-found.

Next

Sources in the code and the knowledge base
  • CIAS/cias-user – User, UserEntity, UserView, UserService (record, page, list), UserAdminController, UserExceptionHandler
  • CIAS/cias-user – V1__cias_user.sql, ArchitectureTest (noCredentialFields)
  • CIAS/cias-user – RegistrationUserHook, UserImportService
  • CIAS/cias-user/docs/adr – ADR-017; CIAS/CLAUDE.md §15, §21, §23
Search