CodamAIDocs
Topicdone

The email is the account

One account per address, any number of tenants. What happens when a known address registers, and why nobody is added to a tenant without consent.

Variants
NEW_ACCOUNTADDITIONAL_MEMBERSHIPknown without tenant → “already registered”abandoned account is taken overlocked account stays lockedolder open attempt is replaced

What this is about

In CIAS, the rule is: one email address is one account. There is no second account for the same address. But one account can be a member of any number of tenants.

This is why every registration first asks: Is there already an account for this address that belongs to somebody? The only exception is the leftover of an abandoned attempt: disabled in Keycloak and the address never verified. Every other account belongs to somebody, a suspended or closed one included.

Which kind of registration

Every registration has a kind (kind):

KindWhenWhat happens to the account
NEW_ACCOUNTThe address has no account, or only a leftover.An account is created disabled (or the leftover is taken over) and enabled after the click.
ADDITIONAL_MEMBERSHIPThe address has an account, a locked one included.Nothing. After the click, only membership and roles are added. If the account is locked, the registration fails.

Which email the person gets

Address and tenant decide the email
account for the address?flow assigns a tenant?Email and outcome
no–VERIFY_EMAIL: the link verifies the address, then a new account
yesyesMEMBERSHIP_INVITATION: the link leads to joining the tenant. Password and account stay as they are
yesnoALREADY_REGISTERED: “You already have an account”, with a link to sign in

The links in the emails are valid for as long as the flow defines (token-ttl): 24 hours for self-registration in cias-runtime, 14 days for an invitation.

From the outside, all three cases look the same: the form always responds with 202 accepted. Only the email differs, and only someone with access to the mailbox gets it. This way, you cannot find out through the API whether an address has an account.

Special cases

What happens to half-finished and duplicate attempts

When: There is an account in Keycloak for the address that was never enabled, for example from a registration whose link was never clicked.

The account is disabled and its address was never verified, so it counts as a leftover. The new registration is therefore NEW_ACCOUNT, but it does not create a second account. It takes over the existing one. After the click, the account is enabled.

Result: No account graveyard, no error message “address already taken”.

When: The account is suspended or closed. In Keycloak it is disabled, but its address is verified.

The account belongs to somebody. The registration is ADDITIONAL_MEMBERSHIP and answers 202, like for every known address. When the person redeems the link, the registration fails with 422 cias.registration.account-locked before a tenant or roles are assigned. This also holds if the account was locked while the email was on its way.

Result: Only an administrator lifts a lock. A verified address is no reason to.

When: The same address still has a registration that is waiting for the click or for approval.

The older registration moves to EXPIRED right away. Only the link from the newest email is valid. A click on the old link no longer changes anything.

Result: If you cannot find the first email, you simply register again.

Next

Sources in the code and the knowledge base
  • CIAS/cias-registration – RegistrationService (register: findByEmail, supersedeOpenAttempts, mailPurpose, tokenPurpose), RegistrationKind
  • CIAS/cias-registration – RegistrationService (isSomebodysAccount, provision: requireUnlocked)
  • CIAS/cias-user – RegistrationUserHook (onCompleted: activate only for PENDING)
  • CIAS/cias-registration – RegistrationServiceTest (takeover, replacement, LockedAccount)
  • CIAS/cias-registration/docs/adr – ADR-014
Search