Realms
A realm is one OIDC issuer — a self-contained login service with its own users, sign-in methods, assurance policy, and signing keys. This page covers creating realms and every setting on the realm settings page.
Creating a realm
In the admin console, open Realms and use the Create Realm card. There is a single field:
- Name — a display label (e.g. Production). It does not affect any URL and can be changed later.
On submit, SemAuth automatically:
- generates a random 12-character issuer ID (DNS-safe, ~62 bits of entropy) and serves the realm at
{issuer_id}.semauth.app; - generates an active RSA 2048 signing key (algorithm
RS256); - sets the defaults: magic link enabled, passkey enabled, and minimum assurance = AAL1 ("Any factor").
The realms list shows each realm's Name, Issuer ID (and custom domain if set),
Status (Active / Disabled), and action links: Apps · Users · IDPs · Events · Settings · Discovery.
The Discovery link opens the realm's /.well-known/openid-configuration.
Realm settings
Open Settings for a realm (/realms/{issuer_id}/settings). There are three cards.
Realm name
Change the display name. The value is trimmed and cannot be empty. Renaming never changes the issuer ID or any URL — it is purely cosmetic.
Authentication policy
The Minimum assurance dropdown sets the lowest authentication strength a sign-in must reach before this realm will issue tokens. Three options:
| Option | Meaning | Satisfied by |
|---|---|---|
| Any factor (AAL1) | Any single factor is enough. | Magic link, passkey, or federation. |
| Require MFA (AAL2) | Multi-factor required. | A passkey (today). One-time-code MFA arrives later. |
| Require phishing-resistant (AAL3) | A phishing-resistant credential required. | A passkey. |
Guardrail. Because a passkey is currently the only factor stronger than AAL1, you
can only select Require MFA or Require phishing-resistant when passkeys are
enabled for the realm. Trying to set an unreachable floor is rejected ("This assurance level requires passkeys…")
so you can't accidentally lock every user out at /authorize.
The full model — how each sign-in method maps to an assurance level, what the acr claim contains,
and how step-up works — is on the Assurance levels page.
Enabling/disabling magic link & passkey. The two sign-in-method toggles
(magic_link_enabled, passkey_enabled) are currently only changeable through the
Admin API (PATCH /v1/realms/{issuer_id}), not from the settings
page. New realms have both enabled.
Custom domain
Serve a realm at your own brand-aligned hostname (e.g. idp.acme.com) instead of the default
{issuer_id}.semauth.app. Once active, the custom domain becomes the realm's iss, its
JWKS URL, the link host in magic-link emails, the passkey binding (rp_id), and the federation
callback target. The default host stays reachable as a fallback.
Set it before onboarding users. Changing the custom domain later invalidates every outstanding access token, refresh token, and passkey credential on the realm (the passkey binding is tied to the hostname). Configure it first, then onboard.
How to configure it
- At your DNS provider, add a CNAME record pointing your chosen hostname at the realm's
canonical target shown in the UI:
your-host CNAME {issuer_id}.semauth.app. - Back in the settings card, enter the custom domain and click Verify CNAME & activate.
SemAuth resolves the CNAME chain (up to 5 hops) using public DNS resolvers only (Cloudflare 1.1.1.1 and Google 8.8.8.8) and activates the domain only if it points at the canonical target. TLS certificates are issued automatically on first request.
Rules and common errors:
- Apex domains are refused — use a subdomain (
idp.acme.com), notacme.com. - Platform-owned domains (anything under
semauth.cc/semauth.app) are refused. - If verification fails with "no CNAME record found" or a mismatch, the record may not have propagated yet — DNS changes can take a few minutes; retry shortly.
To remove it, click Clear custom domain. The realm reverts to its canonical host; tokens issued for the custom hostname become invalid.
Signing keys
Each realm has its own RSA 2048 key pair used to sign ID tokens and JWT access tokens with RS256.
The active public key is published at the realm's /jwks.json, which is how resource servers and your
apps verify tokens statelessly. Private keys are stored encrypted at rest. Keys are generated automatically at
realm creation; rotation is event-driven (a new active key is added and the old one deactivated) rather than a
manual button in the console today.
Disabling a realm
A disabled realm stops resolving — its hostname no longer serves OIDC endpoints. Re-enabling restores it.
Realm enable/disable is available through the Admin API
(PATCH /v1/realms/{issuer_id} with enabled).