Self-service registration and progressive profiling
Let people sign themselves into your organisation instead of every account starting from an invite. What is real today, what is only a link to nowhere, and what a login prompt does not yet do.
Self-service registration lets a visitor join your organisation without you inviting them first. Configure it at /iam/governance/registration-policy. It is off by default: an organisation with no policy configured accepts no self-registrations at all, the same as before this feature existed.
The policy is one document, not a list
There is exactly one registration policy per organisation, not a set of rules to manage individually. It has:
- `enabled`
- Whether the public sign-up endpoint accepts anything at all for this org.
- `allowed_domains`
- Optional. Leave empty to accept any email domain; list one or more (e.g.
acme.com) to restrict registration to them. Domains are matched case-insensitively with a leading@stripped if you type one. - `required_attributes`
- Profile attribute names a registrant must supply at sign-up, such as
department. Missing one refuses the registration with that attribute's name in the error. - `default_group_ids`
- Groups a successful registrant is added to automatically.
- `approval_required`
- When true, the account is created inactive and cannot sign in until an administrator approves it.
- `progressive_attributes`
- A separate list — see progressive profiling below — of attributes not required at sign-up but checked for later.
Saving is PUT /organizations/{orgID}/registration/policy; reading is the matching GET. Both require iam:governance.read/write respectively, same as the rest of this module.
The public endpoint, and the link the console hands you
The actual sign-up surface is GET/POST /public/register/{orgSlug} — unauthenticated, mounted outside the ordinary tenant and session middleware, because the person calling it is by definition not yet a member of anything. GET returns a public-safe summary of the policy (whether it is enabled, the allowed domains, the required attributes) so a form can pre-validate before the visitor types anything; it never 404s on an unknown organisation slug, answering enabled: false instead, so the endpoint cannot be used to enumerate which tenant slugs exist. POST, by contrast, does return 404 on an unknown slug — the enumeration protection is specific to the read side.
What a successful registration actually does
A registration needs a valid email, a password of at least 8 characters, a first and last name, and whatever required_attributes your policy names, supplied in a profile object. On success it creates the account — inactive if approval_required is set — assigns the organisation's member role, and attempts to add the person to each configured default group.
If the email address already belongs to a user elsewhere in the platform, registration adopts that account into this organisation only if the password supplied matches the existing one — this is deliberate, so the endpoint can never be used as a password-guessing oracle against an email you do not control. If the address is already a member of this specific organisation, it is refused with "this email is already registered in this organization."
Email verification is real and already wired
This is not a gap: a self-registered account gets the same verification token and mailer as password reset already uses, and the mailed link resolves to a real landing page in the console — a verifying / success / invalid screen at /verify-email/:token that spends the token against POST /auth/verify-email/confirm on mount and reports which of the three it got. An expired, already-spent or never-issued token all read the same way on purpose, for the same enumeration-safety reason the password-reset and invite-redemption screens already use.
Progressive profiling
progressive_attributes in the same policy names attributes you are not willing to require at sign-up but still want, eventually — department, cost centre, whatever fits. GET /iam/registration/progressive-profile (authenticated, no {orgID} segment in the path) answers which of those attributes are still missing from the caller's own profile, as {"missing_attributes": [...]}.
Permissions
| Action | Permission required |
|---|---|
| View or save the registration policy | iam:governance.read / iam:governance.write |
| Register through the public endpoint | None — unauthenticated by design |
| Check your own missing progressive attributes | None beyond being signed in |
What to do next
- Signing up, and what actually exists afterwards — how the very first account in an organisation is created, which self-service registration does not change.
- Who actually needs a Qorionix account — the invite-based alternative to self-service registration, still the only path with a real console screen behind it end to end.
- Profile fields and custom attributes — before you name a
required_attributesorprogressive_attributesentry that does not match a real attribute.