The Challenges & Security screen holds the per-tenant settings that auth reads while it signs a user in and issues tokens: one-time-password templates, session lifetimes, throttling, passkeys, DPoP, mutual TLS, the token signing key and the authorization detail types. Pick the tenant in the sidebar first; every setting on this page belongs to that tenant. Settings for the whole deployment (password policy, login logo) are on System Settings.
Before you start
| Need | Permission |
|---|---|
| See the screen | security:read |
| Add, edit or delete templates, change settings, register authorization detail types | security:manage |
Without security:manage the screen is read-only: the Add Template, Edit and Create Type buttons are not shown.
Central stores the settings and auth loads them through its configuration sync, so a saved change reaches auth after the next refresh, not instantly. Everything on this page takes effect in auth; edge does not read these settings. A tenant that has no settings row yet shows No challenge settings yet with a + Add Challenge Settings button. A tenant created in the console starts with the defaults listed below.

Templates
Templates are the messages auth sends with a code or a temporary password. The section description reads: OTP and temporary-password templates used by OAuth clients; SMS templates are plain text, email templates use HTML.
Each template card shows the template ID and three selectors:
| Selector | Meaning |
|---|---|
| Type | otp (one-time code) or password (temporary password sent when an administrator resets a user’s password). |
| Channel | sms or email. |
| Language | One of the active languages. Active languages come from the Locales screen. |
A template is identified by its ID, type and channel together, so one ID can have an SMS and an email version. A client picks an otp template by ID in its OTP Settings (OTP Template and OTP channel, see Client). A password template is found by channel alone: auth takes the one password template of the channel the administrator chose, whatever its ID.
Add Template opens a form:
| Field | Rules |
|---|---|
| Template ID | Required. Used by clients to refer to the template. |
| Type | otp or password. |
| Channel | sms or email. Email templates must contain valid HTML; the console previews them in a sandboxed frame. |
| Localizations | One text per active language, all required. |
Placeholders are checked when you save, in the console and again in Central:
| Type | Required placeholders | Other placeholders |
|---|---|---|
otp | {{code}} | {{appName}} is replaced with the client’s name in the user’s language. |
password | {{password}} and {{expiresHours}} | none |
When auth picks the text it tries the user’s UI locales first, then the default locale, then any available localization.

The ✕ icon on a card deletes the template for the selected type and channel. Central does not check whether a client still uses the template. A client that points at an ID with no template for its channel has no text to send, so change the client’s OTP Template before you delete the old one.
Challenge Settings
Edit opens Edit Challenge Settings, one form with all the fields below. Save writes the whole form in one request.

OTP and phone numbers
| Field | Controls | Default | Range |
|---|---|---|---|
| OTP Code Length | Digits in a generated one-time code. | 6 | At least 1. No upper limit is enforced. |
| OTP Resend After (seconds) | How long a user waits before asking for a new code. | 60 s | 0 or more. |
| Allowed Phones | Phone prefixes a user may sign in or register with. Empty list: any phone number is accepted. | empty | Each entry is + followed by digits, for example +77. |
Phone numbers are stored and compared in canonical E.164 form, and Allowed Phones is matched against that canonical form. A number typed as +787011234567 (with the national trunk prefix) becomes +77011234567, so it matches the prefix +77 and does not match +78. Write prefixes in the canonical form. The same filter applies to a login_hint that carries a phone number.
Sessions
| Field | Controls | Default | Range |
|---|---|---|---|
| Auth Conversation TTL (seconds) | How long an unfinished sign-in (the sequence of challenges for one authorization request) stays valid. | 900 s (15 min) | At least 1 s. |
| SSO Session TTL (days) | How long the SSO session cookie stays valid after authentication. | 1 day | At least one second; the console takes days and accepts fractions such as 0.5. |
| SSO Session Idle Timeout (seconds) | Online sessions (no offline_access) expire after this much inactivity. It slides forward on each silent re-authentication. | empty (disabled) | Empty, or a positive number of seconds. |
| User Agent TTL (days) | How long a recognized device (user agent) is remembered before it must be verified again. | 180 days | At least one second; fractions allowed. |
Client IP Header
Client IP Header names the HTTP header your reverse proxy sets with the real client IP. auth uses it for IP-based throttling and takes the first value if the header carries a comma-separated list. Default: X-Real-IP. The list offers X-Real-IP (nginx), X-Forwarded-For (other proxies) and Custom…. A custom value must not be empty. If the header is missing on a request, auth has no IP to throttle on.
Submission Limits
Submission Limits throttle repeated attempts. They are shown as chips such as 5 per 15 min in the read-only view.
| Field | Meaning |
|---|---|
| Ban Duration (seconds) | How long a user is banned after exceeding the longest window. |
| OTP Request, OTP Submit, Password Submit, Passkey Assertion | Each category holds one or more windows of Max Attempts per Window (sec). |
Only the longest window of a category triggers a ban. The shorter windows answer with an immediate rate limit. + Add Window adds a row; both numbers must be at least 1. Defaults for a tenant created in the console:
| Category | Windows | Ban duration |
|---|---|---|
| OTP Request | 2 per 60 s, 5 per 3600 s | 1800 s for all categories |
| OTP Submit | 3 per 120 s, 5 per 3600 s | |
| Password Submit | 5 per 900 s, 10 per 3600 s | |
| Passkey Assertion | 5 per 300 s, 10 per 3600 s |
A category you leave without any window is not throttled at all. If auth has no settings row for a tenant, it applies the defaults above. Users who hit a limit can be released from the user card with Reset Limits, see User.
Passkey (WebAuthn)
| Field | Controls | Default |
|---|---|---|
| Relying Party ID | The domain passkeys are scoped to, for example example.com. Required. | The identity domain seeded at bootstrap, empty if none was seeded. |
| Relying Party Name | Name shown to users in passkey prompts. Required. | Versola |
| User Verification | Whether the authenticator must verify the user (PIN, biometrics): required, preferred or discouraged. | preferred |
| Allowed Origins | Full origins permitted to use these passkeys, for example https://example.com. At least one is required. | The origins seeded at bootstrap, empty if none were seeded. |
The console refuses to save the form while the relying party ID, the name or the origin list is empty. A passkey registered for one relying party ID does not work under another, so change Relying Party ID on a running system with care.
Mutual TLS
The Mutual TLS checkbox, This tenant’s reverse proxy terminates mutual TLS, tells auth that a proxy in front of this tenant requests the client certificate and forwards it in a header. With it on, you also choose where the certificate arrives:
| Field | Meaning |
|---|---|
| Certificate Header | The header the proxy sets. Presets: ssl-client-cert (nginx / ingress-nginx, URL-encoded PEM) and X-Forwarded-Tls-Client-Cert (Traefik, Base64-encoded DER). Custom… takes any header name. |
| Encoding (custom only) | URL-encoded PEM (urlEncodedPem) or Base64-encoded DER (base64Der). |
There is no standard for this header, so both values must match your proxy configuration exactly. Header and encoding are saved together; with the checkbox off both are cleared and the read-only view shows no mTLS Certificate Header block. Default: off.
Warning: Central refuses to register a client that carries an mTLS subject while this tenant has no mTLS Certificate Header. The error is
mtlsAuth needs the client's tenant to set mtlsCertificateHeader - without it no certificate ever reaches auth for this client. It applies to a Web app created in the wizard (edgeprovisions its certificate and Central records the subject) and to any client edited to use the mTLS credential. A Mobile or desktop app fronted byedgeis exempt: it reachesauthon its own mTLS listener, which reads the certificate from the handshake, so the header is not consulted. Turn on Mutual TLS and save before you create such a client. See Client and Sender-constrained tokens.
Token Signing Key
Token Signing Key selects the JWKS key that signs this tenant’s access tokens, ID tokens and logout tokens. The list shows only keys Central holds a private half for, written as kid · algorithm. Keys that are published for verification only do not appear. Generate keys on Well Known.
| Option | Result |
|---|---|
| A key from the list | auth signs with that key. Central checks the key when you save. |
| Auth service’s configured key | The setting is empty. auth signs with the private key from its own jwt.private-key configuration, under whatever algorithm that key has. |
A new tenant starts on the most preferred signable key: PS256 first, then ES256, newest kid first. If none exists, it starts on the configured key. RS256 keys are listed only when the tenant uses the Standard security profile. On a FAPI 2.0 tenant Central refuses them (Key '<kid>' signs RS256 ... Select a PS256 or ES256 key instead). The profile is fixed at tenant creation, see Security profiles. Other refusals: an unknown kid, and a verify-only key.
When you switch a tenant to a freshly generated key, auth signs with the new key only after it has synced it. Until then it keeps signing with the previous key, so tokens keep flowing during the switch.
Client Assertions
Maximum Lifetime (seconds) limits how far in the future a private_key_jwt client assertion may set its exp (RFC 7523). auth remembers each assertion’s jti until it expires, so a longer lifetime costs storage; a shorter one rejects clients that mint long-lived assertions.
| Default | Range |
|---|---|
300 s (5 min) | 30 to 900. The console and Central both refuse a value outside it. |
DPoP
Require a DPoP nonce makes every DPoP proof that this tenant’s clients send to /token and /userinfo carry a server-issued nonce (RFC 9449, section 8). A request without a nonce is answered with use_dpop_nonce and a fresh nonce in the DPoP-Nonce header, and the client has to retry. Default: off (Not required).
Turn it on only after every DPoP client of the tenant retries on use_dpop_nonce: one that does not stops getting and refreshing tokens. Clients that do not use DPoP are unaffected. Turning it off takes effect at once and breaks nothing. The setting covers auth’s own endpoints only; calls proxied through an edge follow that edge’s own DPoP Nonce setting on the Edges screen. See Sender-constrained tokens.
ACR Vocabulary
ACR Vocabulary maps ACR names to the authentication factors they require. A client asks for one with the acr_values parameter. Each row has an ACR name (for example company_mfa) and checkboxes for the factors otp, password and passkey. Rows with an empty name or no factor are dropped on save. Default: no entries. The same names appear as Step-up ACR choices on resources, see Resource.
Post-Logout Redirect URIs
Post-Logout Redirect URIs lists where /logout may send the user afterwards. A relying party must send one of them, character for character, as post_logout_redirect_uri (OpenID logout). Each entry goes through the same redirect URI check as client redirect URIs; a rejected entry blocks saving and the error names it. Default: empty.
Authorization Details
This section registers the RFC 9396 authorization_details types that clients of this tenant may request. Create Type opens the form; ✎ edits a type and ✕ deletes it.
| Field | Rules |
|---|---|
| Type | The value clients send as the type member. Lowercase letter first, then lowercase letters, digits and underscores (payment_initiation). |
| Description | Required. Shown in the list. |
| JSON Schema | Required. JSON Schema 2020-12. Detail objects of this type are rejected unless they validate against it; unevaluatedProperties: false rejects unknown members. Central refuses a schema that is not itself a valid JSON Schema. |
The form is prefilled with a starter schema that requires type and allows locations and actions as string arrays. Central adds each type to authorization_details_types_supported in the server metadata and removes it again on delete.

Next steps
- System Settings for the password policy and the login logo
- Well Known to generate and publish signing keys
- Security profiles and Sender-constrained tokens