What this is about
Before someone may use an account, it must be clear that the address belongs to them. For this, CIAS sends an email with a link. Whoever clicks it proves that they can read the mailbox.
CIAS does this itself, not Keycloak. This way, the email, the link, and the flow are the same for all variants and traceable in CIAS.
The flow
sequenceDiagram
participant C as CIAS
participant K as Keycloak
participant M as Email
participant B as User
C->>K: Create account: enabled=false, emailVerified=false
C->>C: Generate token, store only the hash
C->>M: Email with link …/registration/verify?token=…
M-->>B: Email
B->>C: POST /cias/registration/verify { token }
C->>C: Compute hash, find registration, valid?
C->>C: Token used, registration → VERIFIED
Note over C: then approval or provisioning
C->>K: emailVerified=true, enabled=true
Properties of the token
| Property | Value | Why |
|---|---|---|
| Length | 32 random bytes (256 bits), as 43 characters in the link | cannot be guessed |
| Stored | only the SHA-256 hash | Someone who reads the database cannot build a link from it |
| Valid | as long as the flow defines (token-ttl, default 24 hours) | Links in old emails should not work forever |
| Use | once | After that, the token is used up |
| Unique | each hash belongs to exactly one registration |
A hash is a fingerprint: you can easily compute the hash from the token, but not the token from the hash.
The variants
When: Token known, not expired, registration waiting for the click.
The token is marked as used, and the registration moves to VERIFIED. After that, it continues without further action: to approval, if the flow requires one, otherwise straight to provisioning.
Result: 202 { "status": "accepted" }
When: The token was already redeemed. Email programs often open links in advance to check them, and so redeem the token before the person does.
CIAS sees that the registration has already moved on and does nothing. The response is the same as for the first click.
Result: 202, no change.
When: The token does not exist, or it expired while the registration is still waiting for the click.
Both cases get the same response. Someone who guesses links learns nothing.
Result: 404 cias.registration.not-found. The person registers again and gets a new email.
When: The email does not arrive, and a platform administrator has checked the address in another way.
-
1Admin→CIAS
POST /cias/admin/registrations/{id}/activate -
2CIASIs the registration waiting for the click?
-
3CIASmarks the token as used, even if it has expired, registration →
VERIFIED -
4CIAScontinues as after a click
Result: Only for platform administrators.