Challenges & Security — Versola Docs
VersolaVersola/docs
Pre-1.00.7.1versola.kzGitHub

Challenges & Security

Reference for the Challenges & Security screen of the admin console — OTP templates, challenge settings, throttling, passkeys, DPoP, mTLS, signing key and authorization details, per tenant

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

NeedPermission
See the screensecurity:read
Add, edit or delete templates, change settings, register authorization detail typessecurity: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.

Challenges & Security, read-only view (tenant acme)
Challenges and Security page for the acme tenant: the template list, registered authorization detail types, and the read-only Challenge Settings card with OTP length, session TTLs, passkey, DPoP, mTLS, signing key and submission limits.

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:

SelectorMeaning
Typeotp (one-time code) or password (temporary password sent when an administrator resets a user’s password).
Channelsms or email.
LanguageOne 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:

FieldRules
Template IDRequired. Used by clients to refer to the template.
Typeotp or password.
Channelsms or email. Email templates must contain valid HTML; the console previews them in a sandboxed frame.
LocalizationsOne text per active language, all required.

Placeholders are checked when you save, in the console and again in Central:

TypeRequired placeholdersOther 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.

Add Template
Add OTP Template form with Template ID, Type, Channel and one localization text per active language, each containing the {{code}} placeholder.

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.

Edit Challenge Settings
Edit Challenge Settings form: OTP length and resend interval, allowed phone prefixes, session TTLs, passkey settings, client IP header, the mutual TLS switch with certificate header, token signing key and client assertion lifetime.

OTP and phone numbers

FieldControlsDefaultRange
OTP Code LengthDigits in a generated one-time code.6At least 1. No upper limit is enforced.
OTP Resend After (seconds)How long a user waits before asking for a new code.60 s0 or more.
Allowed PhonesPhone prefixes a user may sign in or register with. Empty list: any phone number is accepted.emptyEach 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

FieldControlsDefaultRange
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 dayAt 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 daysAt 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.

FieldMeaning
Ban Duration (seconds)How long a user is banned after exceeding the longest window.
OTP Request, OTP Submit, Password Submit, Passkey AssertionEach 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:

CategoryWindowsBan duration
OTP Request2 per 60 s, 5 per 3600 s1800 s for all categories
OTP Submit3 per 120 s, 5 per 3600 s
Password Submit5 per 900 s, 10 per 3600 s
Passkey Assertion5 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)

FieldControlsDefault
Relying Party IDThe domain passkeys are scoped to, for example example.com. Required.The identity domain seeded at bootstrap, empty if none was seeded.
Relying Party NameName shown to users in passkey prompts. Required.Versola
User VerificationWhether the authenticator must verify the user (PIN, biometrics): required, preferred or discouraged.preferred
Allowed OriginsFull 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:

FieldMeaning
Certificate HeaderThe 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 (edge provisions its certificate and Central records the subject) and to any client edited to use the mTLS credential. A Mobile or desktop app fronted by edge is exempt: it reaches auth on 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.

OptionResult
A key from the listauth signs with that key. Central checks the key when you save.
Auth service’s configured keyThe 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.

DefaultRange
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.

FieldRules
TypeThe value clients send as the type member. Lowercase letter first, then lowercase letters, digits and underscores (payment_initiation).
DescriptionRequired. Shown in the list.
JSON SchemaRequired. 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.

Create Authorization Detail Type
Create Authorization Detail Type form with the Type field, a Description field and a JSON Schema editor prefilled with a 2020-12 starter schema.

Next steps