Core concepts

SemAuth has five nested building blocks: organization → realm → application → client, plus users who belong to a realm. Understanding how they relate is the key to everything else in this documentation.

The hierarchy

flowchart TD subgraph Tenant["Organization (your tenant)"] direction TB R1["Realm A<br/><small>issuer · users · login policy</small>"] R2["Realm B"] end R1 --> A1["Application: Web App"] R1 --> A2["Application: Mobile"] A1 --> C1["Client: SPA (public)"] A1 --> C2["Client: Backend (confidential)"] A2 --> C3["Client: iOS app"] R1 --> U1["Users<br/><small>alice@…, bob@…</small>"]

Organization

The organization is the top-level tenant — usually your company. It owns everything below it and is the boundary of isolation: one organization can never see another's realms, users, or audit events.

The system organization. SemAuth reserves one system organization, operated by Kovilo, whose slug is self. It hosts the platform Admin API. As a customer you never interact with it directly — self is simply a reserved slug, mentioned here only so the term isn't a mystery if you encounter it (for example in the Admin API hostname).

Realm

A realm is an OIDC issuer — a self-contained login service with its own users, sign-in policy, signing keys, and OIDC endpoints. Think of a realm as one "login universe": users in realm A and realm B are completely separate identities even within the same organization.

You typically create one realm per environment or product line — for example a production realm for your live users and a staging realm for testing.

Admin realm. Every organization is itself authenticated by SemAuth (SemAuth "dog-foods" its own OIDC). When you sign up, SemAuth automatically creates a hidden admin realm that authenticates your human administrators into the admin console, and that hosts your Admin API credentials. You don't manage it day-to-day, but it's why you log in to the admin console with the same passwordless flow your own users get.

Application

An application is a grouping of clients inside a realm — it represents one product or service in your portfolio (e.g. "Acme Web", "Acme Mobile"). An application carries a name, an optional description, and optional Terms of Service / Privacy Policy URLs. It does not itself authenticate; it is a container that holds one or more clients.

Client

A client is the actual OIDC relying party — the concrete piece of software that performs the login flow and receives tokens. Each client belongs to exactly one application. A client has a client_id, an authentication method, allowed grant types, allowed scopes, redirect URIs, and (optionally) the API audiences it may request.

Clients come in two shapes:

TypeAuth methodUse for
Publicnone (PKCE-protected)Single-page apps, mobile apps, CLIs — software that can't keep a secret.
Confidentialclient_secret or private_key_jwtBackend / server-side apps that can safely hold a credential.

See Applications & clients for the full registration walkthrough.

User

A user is an end-user identity scoped to a single realm. Users are identified by email and authenticate passwordlessly — via a magic link, a passkey, or a federated provider. The same email in two different realms is two different users. A user can be deactivated (which immediately revokes their sessions and tokens) and reactivated later.

How a login actually flows

When one of your apps sends a user to SemAuth to sign in, the request is routed by hostname to the right realm, the user authenticates, and SemAuth redirects back to your app with an authorization code that your app exchanges for tokens:

sequenceDiagram participant U as User's browser participant App as Your app (client) participant SA as SemAuth realm U->>App: Click "Sign in" App->>SA: Redirect to /authorize (client_id, redirect_uri, PKCE) SA->>U: Show login page (magic link / passkey / federation) U->>SA: Authenticate SA->>App: Redirect back with ?code=... App->>SA: POST /token (code + PKCE verifier) SA->>App: id_token + access_token (+ refresh_token) App->>U: Signed in

The URL scheme

Everything in SemAuth is addressed by hostname. SemAuth uses two domains — semauth.cc for the admin console and semauth.app for realm (issuer) endpoints:

HostWhat lives there
semauth.ccThe public sign-up page.
{org-slug}.semauth.ccYour organization's admin console.
api.self.semauth.ccThe Admin API (self is the reserved system-organization slug).
{issuer_id}.semauth.appA realm's OIDC endpoints (issuer, authorize, token, JWKS…).
idp.acme.com (example)A realm's custom domain, if configured.