Registration control
Closing sign-up is not one switch. Rakomi exposes one switch per account-creation path, because the paths have different trust models — so “registration is closed” is a statement about a set of settings, not about a single field.
This page is the list of those paths, in the order to set them.
The paths, and the switch that gates each
Section titled “The paths, and the switch that gates each”| Path | Switch | Default |
|---|---|---|
| Registration mode (tenant-wide ceiling) | signup_mode (open / closed / invite_only) — set from the dashboard Settings page | open |
| Password / email self-registration | self_registration_enabled | open |
| Social sign-up — Google, GitHub, Microsoft | google_oauth_allow_signup, github_oauth_allow_signup, microsoft_oauth_allow_signup | open |
| Social sign-up — every other configurable provider | the provider’s own allow_signup | closed, and the provider must be enabled explicitly first |
| Anonymous sessions, and their upgrade to a permanent account | the tenant’s anonymous sign-in setting | off |
| Enterprise SSO — just-in-time provisioning | jit_provisioning_enabled on the connection (optionally narrowed by jit_require_group) | provisions unless set to false |
| EUDI wallet sign-in | the EUDI setting for the tenant | off |
| SCIM 2.0 directory sync | administrator-initiated — not gated by any switch on this page; provisioned via the tenant’s own API token, never a stranger’s action | always available when SCIM is configured |
SCIM 2.0 (RFC 7643 Core Schema, RFC 7644 Protocol) directory sync is deliberately excluded from every switch above. Every other row in this table gates a path a stranger initiates — someone authenticating against your tenant for the first time. SCIM provisioning is administrator-initiated: your own API token acts, not a stranger, so none of the switches on this page — including a closed registration mode — affect it.
The registration mode
Section titled “The registration mode”signup_mode is the tenant-wide registration-posture ceiling — open, closed, or
invite_only. It is broader than self_registration_enabled, which gates the password/email
endpoint alone. The ceiling caps password/email self-registration, both anonymous-session-claim
variants, EUDI wallet sign-in, the enterprise-SSO just-in-time fallback — and social sign-up, for
every provider, Google, GitHub, Microsoft and Apple as well as every other configurable one.
The per-provider allow_signup switches stay meaningful underneath it: they decide which providers
admit new users while the mode is open. They cannot re-open a path the mode has closed. The
refusal a stranger sees is not one uniform shape across the paths — treat “was the account created”
as the contract, not the specific error envelope of any one flow.
Composing the settings: a per-provider override, if set, wins; otherwise the tenant-wide floor
(signup_default) applies — and both are capped by the tenant-wide mode above. If the mode is
closed, no per-provider override or floor value re-opens registration until the mode itself
changes.
invite_only is a fully accepted value: registration is refused unless the person has a live
invitation for their exact email address. Send invitations from the dashboard’s Settings page
(Owner role) — each one is a single-use, expiring (7-day) token tied to one email address. The
invited person completes registration either by following the link in the invitation email, or by
supplying their invited email directly to any registration channel:
- Password / email registration requires the invitation’s own token (carried automatically by
the email link, as
?invite=<token>on the register page) — the registrant types their own email into the form, so a bare email match is not enough proof of receipt. - Social / OAuth-first sign-up (Google, GitHub, Microsoft, Apple, and every other configurable provider) needs no token — the identity provider’s own verified email claim is the proof, and a matching live invitation for that email is sufficient.
- Enterprise SSO just-in-time provisioning and EUDI wallet sign-in are capped by the tenant-wide
ceiling exactly as they are for
closed—invite_onlydoes not add a per-connection invitation step to those channels; usejit_require_group(SSO) or turn off EUDI wallet sign-in if you need to restrict those specifically.
An invitation is single-use: it stops being valid the moment the registration it was for succeeds, and it cannot be reused for a second account.
See the invite-only registration recipe
for a runnable, end-to-end example of the password/email variant: validating the token before
showing the form, submitting it with invite_token, and handling every refusal shape (including
why the register endpoint deliberately answers every invite-related failure with the same opaque
code, unlike the more specific validate lookup).
A tenant that existed before this feature shipped never explicitly set signup_mode: its value
was derived once, at migration time, from its self_registration_enabled setting at that time
(true → open, false → closed).
signup_closed_reason is a free-text field visible in the dashboard UI to every admin of the
tenant. Do not put personal data about a named third party in it.
The default, and gating a launch
Section titled “The default, and gating a launch”Every new tenant starts with signup_mode: open. This is the deliberate platform default —
self-serve sign-up “just works” the moment you create a tenant, with no switch to flip first. It is
not a placeholder value waiting for you to configure something; it is the intended starting posture
for an Auth-as-a-Service tenant.
If you are not ready for strangers to create accounts yet — you are still building, or you want to
control who gets in first — switch signup_mode before you publish anything that points at your
tenant, not after:
invite_onlyif you want to onboard a known set of people yourself and let them refer others under your control (see the invite-only recipe above).closedif account creation should wait until you flip it back — existing users keep signing in either way (see Existing users always keep signing in).
Setting the mode is entirely yours to do, at any time, from the dashboard Settings page — nothing about the platform’s default forces a particular launch sequence on you. The point of documenting the default here is so it is a conscious choice, not a surprise discovered after a stranger has already registered.
Minor protection and social sign-up
Section titled “Minor protection and social sign-up”A tenant can turn on minor protection, which requires collecting a date of birth at registration so users under the tenant’s configured age threshold are recognized and handled under the tenant’s own parental-consent policy. This was originally a password/email-only control. It now applies everywhere a stranger can create an account — password/email, every social provider (Google, GitHub, Microsoft, Apple, and every other configurable one), the EUDI wallet channel, and claiming an anonymous session into a permanent account.
Social sign-up itself is not extended with an age-collection step. Instead, when minor protection is on for a tenant, account creation through any of those channels is refused: the visitor is sent back with a message that new-account registration is not available through that method, and is directed to the tenant’s own registration form (which does collect the necessary information) or to contact the tenant administrator.
What an integrator’s application receives:
- On the hosted consent screen for Google, GitHub, Microsoft or Apple, the browser is
redirected back to your application’s OAuth error page with
error=minor_protection_signup_blocked. - On every other channel — a provider your own client drives directly, and the EUDI wallet
channel — the API responds with 403 and error code
tenant/social_signup_blocked_minor_protection.
This is the same refusal shape family as signup_disabled above, and the same rule applies:
treat “was the account created” as the contract, not the exact envelope of any one flow.
Existing users are unaffected. Signing in with an already-linked provider, and linking a new provider to an account that already exists in the tenant, never evaluate minor protection — only the creation of a brand-new account does.
Minor protection, its age threshold, and whether parental consent is required are tenant-wide
settings, configured from the dashboard Settings page next to signup_mode above. They are not
a row in the table above because they do not close a path outright — they add an age condition
to every creation path that table already covers.
Closing every path
Section titled “Closing every path”- Set
self_registration_enabledtofalse. - Set
allow_signuptofalsefor every social provider you have enabled. Each configurable provider carries the flag on its own settings. - If you use anonymous sessions, turn them off for the tenant. Upgrading an anonymous session into a permanent account is a different flow from self-registration and is not covered by the switches above, and the tenant-level anonymous setting is the control for it. Removing the upgrade step from your own UI is not a substitute — the endpoint stays callable by anything holding an anonymous session token.
- If you have an enterprise SSO connection, set
jit_provisioning_enabledtofalseon it explicitly. Leaving it unset provisions new users on first successful sign-in, which is usually what an SSO customer wants and is exactly what you do not want while sign-up is closed.jit_require_groupnarrows provisioning to one directory group if you want it open but bounded. - If you have enabled EUDI wallet sign-in, it admits users on a successful presentation. Turn it off for that tenant if closed sign-up is a requirement.
Steps 3–5 cover features that are off unless you turned them on. If you have not enabled them, they are not open paths for you.
Read the effective state back from GET /v1/auth/config, which reports
self_registration_enabled alongside the tenant’s enabled providers. The registration mode and
floor (signup_mode, signup_default) are not part of that response — read and set them from
the dashboard’s Settings page instead; the public API deliberately does not expose the mode.
Existing users always keep signing in
Section titled “Existing users always keep signing in”Every switch on this page gates account creation. None of them gates login.
A user who already exists in the tenant signs in normally under a closed sign-up —
including the first time they use a social provider, provided the email on the
provider account matches theirs. Rakomi attaches the provider to the existing account
instead of treating it as a new sign-up. A user who does not exist receives a
signup_disabled error on the redirect instead of an account.
That is what makes the common invite-only shape work:
Provision your users up front (directory sync, CSV import, or the admin API), close every path above, and let people sign in with the identity provider your company already uses. Colleagues get in. Everyone else is refused.
Two details to get right before relying on it:
- The match is on the email address. A staff member whose provider account uses a different address than the one you provisioned is a new user as far as Rakomi is concerned, and a closed sign-up refuses them. Provision the address they actually sign in with.
- Provision users as email-verified. An account imported without a verified email is treated as unclaimed, so the first successful social sign-in on that address takes ownership of it. Importing as verified keeps you in control of who owns the account.
When to use an enterprise connection instead
Section titled “When to use an enterprise connection instead”The recipe above is an allow-list by provisioning: access is bounded by the set of
users you created. It is not an allow-list by domain — there is no setting that
means “anyone with an @example.com address may sign up, nobody else.”
If that is what you want, use an enterprise connection (SAML or OIDC) rather than social sign-in:
- you map your email domains to the connection, so users at those domains are routed to your identity provider;
- new users are provisioned just-in-time on first successful sign-in, which you can further restrict to a group in your directory;
- the boundary is enforced by your identity provider — someone outside your organisation has nothing to authenticate against at all.
It also revokes correctly: when your directory disables someone, they lose access. A rule that merely matches on the email domain does not, because the address outlives the employment.
See the SAML SSO guide to set one up.
What these switches do not do
Section titled “What these switches do not do”- They do not remove an existing user. Closing sign-up affects who can be created.
- They do not disable a provider. A provider with
allow_signupset tofalsestays available for login — that is the point. To take it off the sign-in screen entirely, disable the provider itself. - They do not apply retroactively. Accounts created before you closed sign-up remain.