FerrisKeyDocs

Realms

A realm is the top-level isolation boundary in FerrisKey. Users, clients, roles, credentials, scopes, and sessions each belong to exactly one realm. Realms make multi-tenancy possible: one FerrisKey deployment can serve many independent organizations.

What a realm isolates

Each realm is a self-contained identity domain:

ResourceWhat it holds
UsersAccounts, profiles, and credentials
ClientsApplications registered for authentication
RolesPermission bundles and role mappings
CredentialsPasswords, TOTP secrets, WebAuthn passkeys
Client scopesToken claim definitions and protocol mappers
SessionsActive user sessions
ConfigurationToken lifetimes, registration policies, feature toggles

Nothing leaks between realms. A user in realm A cannot authenticate against a client in realm B.

graph TD
    FK[FerrisKey Instance]
    FK --> R1[Realm: master]
    FK --> R2[Realm: my-app]
    FK --> R3[Realm: staging]

    R1 --> U1[Admin Users]
    R1 --> C1[Admin Clients]

    R2 --> U2[App Users]
    R2 --> C2[App Clients]
    R2 --> RO2[Roles]
    R2 --> SC2[Scopes]

    R3 --> U3[Staging Users]
    R3 --> C3[Staging Clients]

The master realm

Every deployment has a master realm. It is created on first boot, holds the initial admin user, cannot be deleted, and is where cross-realm administration happens.

Do not use master for applications

Keep master for administration. Give each application its own realm.

Realm settings

Every realm carries its own settings. They control how sign-in behaves, how long tokens live, and which optional features are on. Read them with GET /realms/{realm_name} and change them with PUT /realms/{realm_name}/settings: a field you leave out keeps its value.

Sign-in and registration

SettingDefaultDescription
user_registration_enabledfalseAllow self-service registration
forgot_password_enabledfalseEnable the password reset flow
remember_me_enabledfalseShow a “Remember me” checkbox on the login page. See sessions and the SSO cookie
magic_link_enabledfalseEnable magic link sign-in by email
magic_link_ttl15How long a magic link stays valid, in minutes
passkey_enabledfalseAllow passkey (WebAuthn) sign-in
require_mfafalseForce every user in the realm to enroll in MFA
login_aliases[username]Ordered list of identifiers accepted at login, from username and email. Must be non-empty and free of duplicates. The first alias that resolves a user wins
edit_username_enabledfalseLet users change their own username
email_verification_enabledfalseRequire users to verify their email
email_verification_ttl_hours24How long a verification link stays valid
compass_enabledtrueRecord authentication flows with Compass

Token lifetimes

SettingDefaultDescription
default_signing_algorithmRS256JWT signing algorithm
access_token_lifetime300Access token TTL, in seconds
refresh_token_lifetime86400Refresh token TTL, in seconds. Also the lifetime of the SSO session
id_token_lifetime300ID token TTL, in seconds
temporary_token_lifetime300Temporary token TTL, in seconds, used while required actions are pending

A client can override each lifetime for itself. See Tokens.

When a user signs in, FerrisKey opens an SSO session and sets the FERRISKEY_SSO cookie, which lets the user move between the applications of the realm without signing in again. The cookie is HttpOnly, SameSite=Lax, scoped to the path /, and marked Secure when the request came in over https.

By default it is a browser-session cookie and disappears when the browser closes. With remember_me_enabled on, the login page shows a “Remember me” checkbox. When the user ticks it, the cookie becomes persistent, with a Max-Age equal to the remaining lifetime of the session. A session lives as long as the refresh token lifetime of the client the user signed in through: the client’s own override, or the realm’s refresh_token_lifetime. The checkbox appears only while the setting is on, and the server ignores a ticked box otherwise.

Ending the session, by logout or by revocation, also revokes every token issued under it.

Lockout

After too many failed attempts, an account is locked for a fixed window.

SettingDefaultDescription
lockout_threshold10Failed attempts before the account locks
lockout_duration_seconds900How long the lock lasts

Audit privacy

SeaWatch can strip or pseudonymise personal data before an event is stored.

SettingDefaultDescription
seawatch_pii_modeoffOne of off, mask, pseudonymise
seawatch_pseudo_keyunsetHMAC key used when the mode is pseudonymise

Locales

SettingDefaultDescription
default_localeenLocale used when the user has expressed no preference. Must be one of supported_locales
supported_locales[en]Locales the login pages offer. Never empty

A locale is a language tag of two letters, optionally followed by a two-letter region: en, zh-CN. A malformed tag, an empty list, or a default that is not in the list is refused with 422. The console and the login pages are translated into en and zh-CN.

A user’s own choice is stored on the user and set through PUT /realms/{realm_name}/users/@me/locale; sending null clears it. The locale picks the language of the console and the login pages. It does not touch emails: each email type is sent with the template configured for the realm, whatever the locale.

Webhook retries

Leave these unset and the realm uses the server defaults.

SettingDefaultDescription
webhook_retry_max_attemptsunsetHow many times a failed delivery is retried
webhook_retry_base_delay_msunsetDelay before the first retry, in milliseconds
webhook_retry_max_delay_msunsetCeiling for a single backoff interval
webhook_retry_max_total_delay_msunsetCeiling for the whole retry sequence

A consent decision is stored for each user and client, and it stays valid for 30 days. The settings API has no field for that duration. The consent page covers when the screen appears.

Client registration and resources

These settings let applications that you have not registered by hand, such as MCP clients, reach the realm. Each is off or empty by default. The MCP page explains the flows.

SettingDefaultDescription
dcr_enabledfalseLet applications register themselves anonymously with POST /realms/{realm_name}/clients/register. Discovery then publishes registration_endpoint. These clients always require consent
cimd_enabledfalseAccept an https URL as a client_id and read the client’s metadata from it. Discovery then sets client_id_metadata_document_supported. These clients always require consent
cimd_allowed_hosts[]Host names a client ID URL may point to, as bare names without scheme or path. Empty accepts any host
allowed_resources[]The RFC 8707 resource indicators a client may ask an audience for: absolute https URLs, or http on a loopback host, without a fragment. Empty accepts none, and a request with a resource fails with invalid_target

Branding and email templates

SettingDefaultDescription
reset_password_template_idunsetTemplate used for password reset emails
magic_link_template_idunsetTemplate used for magic link emails
email_verification_template_idunsetTemplate used for verification emails

Leave a template id unset and FerrisKey falls back to the built-in default for that email type.

The portal theme is not set here

A realm does carry an active portal theme, but it is not a field on this endpoint. Activate one with POST /realms/{realm_name}/portal/themes/{theme_id}/activate, described in Portal.

Reading settings from the login page

GET /realms/{name}/login-settings

The login-facing subset of a realm’s settings, which is what the portal reads to know which sign-in methods to offer: whether registration is open, whether magic links and passkeys are enabled, which identifiers and locales are accepted, and the theme. It needs no authentication. Use it rather than the full settings read when all you need is to render a login page.

SMTP configuration

SMTP lives on the realm too, so two realms in the same deployment can send from different providers and different addresses. The Email & Templates guide covers the fields and the API.