Registering a site¶
Before anyone can sign in to your site, the provider needs to know it: its name, and the exact addresses people are sent back to. That record is a client, and you make one yourself. No email, no waiting on anyone.
Two ways, same result:
- The form. Open auth.omxus.com/developers,
fill in the name and redirect URIs, and leave with a
client_idand snippets to paste. - The API.
POST /oidc/register, standard OIDC Dynamic Client Registration (RFC 7591). The form calls this.
A client on its own is worth almost nothing: it signs nobody in and reads no claim. Every sign-in still needs a real person at the sign-in page, an exact-match redirect URI and PKCE. That is why registration can be open.
The request¶
curl -s https://auth.omxus.com/oidc/register \
-H 'content-type: application/json' \
-d '{
"client_name": "Vex",
"redirect_uris": ["https://vex.example/callback"]
}'
Untested against production on purpose (each call makes a real client). The same call with an empty body was run on 30 Oct 2026 and returned the 400 shown under Errors.
| Field | Required | Values |
|---|---|---|
client_name |
yes | 1 to 80 characters, shown on the sign-in page |
redirect_uris |
yes | array of 1 to 10 URIs, see Redirect URIs |
token_endpoint_auth_method |
no | none (default), client_secret_post, client_secret_basic |
door |
no | minimal (default), full, standard, see Doors |
username_scope |
standard door only | shared (default), site |
theme |
standard door only | omxus (default), horror, gold, tome |
sector_identifier_uri |
no | see One person, several apps |
The answer¶
201 Created (the client_id here is made up):
{
"client_id": "q3V8n0bX1kZ2mH7cT9wLpA",
"client_name": "Vex",
"redirect_uris": ["https://vex.example/callback"],
"token_endpoint_auth_method": "none",
"door": "minimal",
"grant_types": ["authorization_code"],
"response_types": ["code"]
}
client_idis 22 random characters (16 bytes, base64url). It carries no part of your site name, so nobody can guess another site's id.- A standard-door client also gets
refresh_tokeningrant_types, and itsusername_scopeandthemeback. - A confidential client (
client_secret_postorclient_secret_basic) gets aclient_secret. It is shown once. The provider keeps only its SHA-256, so nobody, including the provider, can read it back. Lose it and register again.
Public or confidential¶
If your code runs in a browser or an app on someone's phone, it cannot keep a
secret: register with none (the default). PKCE is required for every
client here, confidential ones too, so a public client is not a weaker one.
If your code runs only on your server, you may take a secret and send it to
the token endpoint in the body (client_secret_post) or as HTTP Basic
(client_secret_basic).
Redirect URIs¶
Matched character for character at sign-in. https://vex.example/callback
does not match https://vex.example/callback/.
Allowed:
https://anywhere;http://onlocalhost,127.0.0.1or[::1]only, for development;- a native app's reverse-DNS scheme, such as
com.example.app:/callback(RFC 8252). Public clients only: an app binary cannot keep a secret.
Refused: a fragment (#…), a relative URI, and any other scheme
(javascript:, data:, file:, a bare app name).
Names¶
client_name is shown to people at the moment they trust the page, so it is
checked:
- it must not contain "omxus" or "auth", including lookalike spellings
(Cyrillic letters,
0foro,rnform); - it must not be a URL;
- if it looks like a domain, that domain must be one of your redirect hosts.
vex.exampleis fine for a client redirecting tovex.example;bank.exampleis not.
Doors¶
The door is the sign-in screen your people see.
minimal(default): email and password first, everything else folded behind one line.full: the whole Omxus app.standard: ordinary accounts. Email or mobile, a username, a password or passkey, on a plain page or on your own page. One account works on every standard-door site.username_scope: "site"gives your site its own usernames;shareduses the one name across all shared sites.themepicks the look.
username_scope and theme sent with any other door are refused.
One person, several apps¶
By default a person's sub is different at every site (see
How identity is derived). A website and its iOS app
usually want the same sub. Both declare the same sector_identifier_uri:
an https URL on one of your redirect hosts (or their registrable domain)
serving a JSON array of every redirect URI.
The provider does not fetch it at registration. The answer carries
"sector_identifier_status": "pending_operator_approval", and the client
cannot sign anyone in (unauthorized_client) until the provider's operator
approves it (Operator routes). When they do, the file must answer 200 within 5 seconds, be
64 KB or less, follow no redirects, and list every redirect URI you
registered.
Limits¶
Ten registrations an hour from one address. Malformed requests count too.
Errors¶
Every error is { "error": "...", "error_description": "..." }.
| Status | error |
When |
|---|---|---|
| 400 | invalid_client_metadata |
no JSON body; bad name, auth method, door, username_scope, theme or sector URI |
| 400 | invalid_redirect_uri |
not 1 to 10 URIs, or one breaks the rules above |
| 429 | too_many_requests |
eleventh registration within the hour |
{
"error": "invalid_client_metadata",
"error_description": "client_name must be 1 to 80 characters"
}
Next¶
Point your library at https://auth.omxus.com:
Add sign-in to a site, or
Any app, via OIDC for the full flow.