Appearance
Central onboarding
Central onboarding is the gateway-controlled completion flow used when a platform requires profile data before it receives a handoff. The identity UI (identity-web) hosts the user interface as one more step of the sign-in, while the Central Auth Gateway remains authoritative for the schema, values, completion state, and continuation of the login transaction.
This page documents the complete central-mode flow and the identity UI implementation. For the shared status model and the other onboarding modes, see Onboarding.
When the flow runs
A platform enters this flow when all of the following are true:
default_onboarding_modeiscentralcentral_onboarding_enabledistrue- the gateway-calculated onboarding status is not
COMPLETE
The same page also runs for every platform, whatever its mode, while a required global profile field is missing. That is always the first step: the URL carries scope=global and the page asks only for the global fields. For a central-mode platform the gateway follows it, after resume, with the platform page described here. On either page only fields without a value are shown.
The gateway does not issue a platform handoff at this point. After the identity callback it creates an HttpOnly gateway session and redirects the browser to the identity UI of the environment that signed the user in:
text
{identity host}/env/{key}/onboarding?platform={platformKey}&resume={transactionId}{identity host}is the origin of the environment's issuer, e.g.https://identity.iesf.ggfor PROD orhttps://dev.identity.iesf.ggfor DEV.{key}is the environment's path key when the issuer is{identity host}/api/auth/env/{key}(an environment that shares its host), otherwisedefault. identity-web turns the prefix into its environment cookie and continues at/onboarding?…, so the page talks to the same environment that issued the login and non-production environments show the environment ribbon.platformselects the server-managed field schema.resumeis the opaque UUID of the original authentication transaction. It is not proof that onboarding is complete.scope=global(optional) switches the page to the global profile APIs:GET /v1/onboarding/global/requirementsandPUT /v1/onboarding/global/values. Instead of the platformcompletecall it readsGET /v1/onboarding/global/status, then resumes; the gateway re-checks the global requirements itself.
End-to-end sequence
If the resume-time evaluation is still incomplete, the gateway redirects the browser back to the same onboarding page. Client-side state never bypasses this check.
Where the page finds the gateway
identity-web is one static build that serves every environment, so the gateway address is not compiled in. The page reads it from identity-api's environment endpoint:
http
GET /api/auth/environment
→ { "key": "PROD", …, "gatewayUrl": "https://auth.iesf.gg" }gatewayUrl is identity-api's GATEWAY_PUBLIC_URL (an origin) or null. It never comes from the page URL, so a crafted link cannot send the form to another server. When it is null, the page explains that central sign-in is not set up and calls nothing.
Page layout
The step uses the sign-in design: the IESF logo and one centred card (the wide 640 px variant).
- eyebrow One more step, title Complete your profile, and "{platformDisplayName} needs a few details before you continue."
- schema-driven fields on a six-column grid.
uiConfig.widthmakes a field full, half or third width from 640 px up; on phones every field is full width.TEXTAREAandMULTI_SELECTare always full width. - a small heading wherever a new
uiConfig.sectionstarts - one primary Save and continue action (Continue when the platform has no active fields)
- a short checkmark animation after completion ("You're all set — Continuing to {platform}…"), then the browser goes to the gateway's resume endpoint
Loading and rendering requirements
The page requests:
http
GET /v1/onboarding/{platformKey}/requirementsThe response supplies platformDisplayName, requirementVersion, active field definitions, and each field's currentValue. The page sorts fields by sortOrder and maps fieldType as follows:
| API field type | Control and submitted value |
|---|---|
TEXT | Text input → string |
TEXTAREA | Multiline input → string |
NUMBER | Number input → number |
BOOLEAN | Checkbox (its text is the field's placeholder, or "Yes") → boolean |
DATE | Date input → YYYY-MM-DD string |
SELECT | Single select → option value |
MULTI_SELECT | Checkbox group → string array, in option order |
COUNTRY | Two-letter text input, upper-cased while typing → country code |
PHONE | Telephone input → international phone string; spaces, dashes, dots and brackets are removed |
EMAIL | Email input → string |
URL | URL input → string |
Text values are trimmed. Empty scalar values are submitted as null; an empty multi-select is submitted as []. Canonical profile fields get the matching browser autofill hint (given-name, family-name, bday, …).
The page uses only safe schema metadata:
label,placeholder, anddescriptionvalidation.minLength,validation.maxLength,validation.min,validation.max, andvalidation.patternoptionsfor select controlsuiConfig.width,uiConfig.section, anduiConfig.helpText
uiConfig is never interpreted as HTML or executable content.
Validation, save, complete, and resume
Before anything is sent, the page checks every field with the same rules the gateway applies (required values, length, pattern, number range, date, country code, + international phone format, e-mail, http(s) URL, known option). Problems appear under their fields; the first one receives focus. A required BOOLEAN is satisfied by either answer, exactly as on the gateway.
Submission is then deliberately sequential:
- Convert the form state to the documented API types.
- Send the complete field map to
PUT /v1/onboarding/{platformKey}/values. - Call
POST /v1/onboarding/{platformKey}/complete. - Require the returned status to be
COMPLETE. - Show the completion animation, then navigate the browser to
GET /v1/auth/resume?transaction={transactionId}.
The page never appends completed=true or treats a successful value write as completion. The completion endpoint verifies all active required fields, and the resume endpoint repeats the server-side evaluation before issuing a handoff.
The page requires both platform and a valid resume UUID. Without them it shows "This link is incomplete" and calls nothing. Platforms that want users to edit these details later do so in their own UI (platform mode APIs).
Authentication, cookies, and CORS
Onboarding API calls use credentials: include and authenticate with the HttpOnly gateway cookie established during the central callback. The credential is not exposed to identity-web JavaScript.
The gateway trusts the identity UI hosts automatically: the host of IDENTITY_ISSUER and of every active identity environment's issuer are part of the CORS and cookie-write Origin allowlist, so they need no CORS_ORIGINS entry.
Deployment must satisfy all of these conditions:
- identity-api's
GATEWAY_PUBLIC_URLis the public gateway origin (https://auth.iesf.gg) - the identity UI hosts and the gateway are same-site (e.g.
identity.iesf.gg,dev.identity.iesf.ggandauth.iesf.ggall underiesf.gg), because the gateway cookie isSameSite=Laxand is not sent on cross-site requests - credentialed CORS responses return the exact allowed origin, not
* - production uses HTTPS
For local development, note that identity.localhost and localhost are different sites, so a gateway on http://localhost:8080 does not receive its cookie from a page on http://identity.localhost:3100. Run the gateway on a host under the identity host (for example auth.identity.localhost) when you test the full flow in a browser.
Error and retry behavior
| Failure | User-visible behavior |
|---|---|
platform or resume missing or malformed | "This link is incomplete", no gateway call |
gatewayUrl not configured | "This step isn't available", no gateway call |
| Requirements cannot be loaded (network, 5xx) | "We couldn't load this step" with Try again |
Gateway session missing or expired (401) | "Your sign-in has expired": go back to the app and sign in again |
| Field fails the client-side rules | Message under the field, field shakes, focus moves to the first problem; nothing is sent |
Value validation fails at the gateway (400) | Form message; a field named in the error details is marked; entered values remain |
Schema changed while filling in (404 on save) | Form message asking to reload the page |
Completion returns incomplete (409) | User remains on the form with an error |
| Resume evaluation is incomplete | Gateway redirects back to the same onboarding page |
No failed request is treated as a successful completion, and values are never replaced with mock data.
Operational setup
Before testing a central flow:
- Register the platform and its callback/return URL pairs in Card Admin.
- Set its default onboarding mode to
central. - Enable central onboarding.
- Add and activate the required field definitions in
/admin/onboarding. - Set identity-api's
GATEWAY_PUBLIC_URL, and make sure the identity environment's issuer is active in the gateway. - Start authentication through
/v1/auth/startfor that platform.
Changing an active field definition increments the platform requirementVersion. Previously complete users become IN_PROGRESS and will see central onboarding again on their next central-mode authentication when they no longer satisfy the current schema.
Security invariants
- The platform key and onboarding policy come from the server-side registry.
- The gateway address comes from identity-api configuration, never from the page URL.
- The
resumetransaction must be bound to the authenticated gateway-session user and to the same identity environment. - The identity UI never creates a handoff code.
- Only the gateway can mark the current requirement version complete.
- Resume re-checks the active platform, transaction, user, and onboarding state.
- Profile fields update canonical profile storage; custom fields remain platform-scoped.
- The gateway token and one-time handoff code are never stored in browser-readable application state.