A security profile is a per-tenant setting that decides which clients the tenant admits and how strictly auth treats their requests. There are two: fapi2 (the default) and standard (discouraged, kept only for compatibility). You pick one when you create the tenant, and it cannot be changed afterwards.
What a profile is
Every tenant has exactly one security profile. It is enforced twice:
- At registration.
centralrefuses to create or update a client whose settings the tenant’s profile does not admit, and lists every violation in one error. - At runtime.
authapplies stricter rules to requests from the tenant’s clients: who may authenticate at/token,/par,/introspectand/revoke, what a client assertion or request object must contain, whether PKCE is optional.
The two profiles:
| Profile | Intent |
|---|---|
fapi2 | Requirements from the FAPI 2.0 Security Profile: confidential clients only, no shared secrets, sender-constrained tokens, pushed authorization requests. The default. |
standard | Plain OAuth 2.0 / OpenID Connect. Admits client secrets, public clients, RS256 signing keys and private-use redirect schemes. Discouraged: kept only for compatibility with clients that cannot meet fapi2. |
Both profiles apply a set of rules that do not depend on the choice, for example S256 as the only PKCE method, nonce required when response_type includes id_token, and refusal of plain http redirect URIs to non-loopback hosts.
Comparison
| Aspect | fapi2 (default) | standard |
|---|---|---|
| Client authentication | private_key_jwt, tls_client_auth or self_signed_tls_client_auth only | Also client_secret, or none (public client) |
| Public clients and client secrets | Refused at registration. A public client that exists anyway gets invalid_client at /token, /par, /introspect and /revoke | Allowed |
| Sender-constrained tokens | Required: DPoP (dpopBoundAccessTokens) or certificate-bound tokens | Optional per client |
| PKCE | S256, required for every client | S256. A confidential client may omit it; public clients and clients of edge-fronted native apps still need it |
| Pushed authorization requests (PAR) | Required for every client that has a redirect URI | Optional per client (requirePushedAuthorizationRequests) |
| Redirect URIs | https. Loopback http only for native clients, or for any client when the deployment is not in prod | https, loopback http, and reverse-domain private-use schemes (for example com.example.app:/callback) |
| Token signing key | PS256 or ES256. RS256 is refused (400) | PS256, ES256 or RS256 |
Client assertion aud | Exactly the issuer string | The issuer, or the issuer with the endpoint path |
| Request objects | nbf and jti required. aud is exactly the issuer string | nbf optional. jti optional, replay-checked when present. aud is the issuer or the issuer with /authorize |
Hybrid flow (response_type=code id_token) | nonce required | nonce required |
The jti replay guard for request objects and client assertions applies under both profiles.
Immutability and defaults
The profile is fixed when the tenant is created.
POST /configuration/tenantstakes an optionalsecurityProfile(standardorfapi2). When omitted, the tenant getsfapi2.PUT /configuration/challenges/challenge-settingsaccepts the tenant’s current value and refuses any other with400.- The value is stored with the tenant’s challenge settings and returned in the settings payload as
securityProfile.
There is no switch from standard to fapi2 later. To move, create a new tenant with the profile you want and register the clients again.
How to choose
Use fapi2. The standard profile is discouraged: it is kept only for compatibility with clients that cannot meet fapi2, and a tenant on it gives up the protections listed above. Pick it only when a client you must support cannot meet fapi2, for example:
- A third-party application that authenticates with a client secret and does not support DPoP or mTLS.
- A public client that calls
authdirectly, such as a single-page application withoutedgein front of it. - An RS256 signing key required by an existing relying party, for example a conformance tool.
Mixing is done with tenants, not clients: put clients that need standard in a separate tenant.
In the admin console
- Tenants. The create form has a Security profile field with FAPI 2.0 (recommended) and Standard. The field is not shown when you edit an existing tenant.
- Clients. The create wizard reads the profile of the tenant. Step 1 shows a plan panel listing the fixed rules for the chosen kind of client (Web app, Mobile or desktop app, Service app). On a
standardtenant the panel adds a note that a client secret, RS256 keys and public native clients are admitted. Underfapi2, a service client chooses betweenprivate_key_jwtand mTLS only. - Challenges & Security. The token signing key list shows RS256 keys only when the tenant is not
fapi2.
Apps fronted by edge stay FAPI-shaped on both profiles. The wizard sets certificate-bound tokens for a web client fronted by edge, and DPoP-bound tokens with an App Link redirect for a native one.
In the Central API
| Field | Where | Values |
|---|---|---|
securityProfile | POST /configuration/tenants request, challenge settings payload | standard, fapi2 |
authMethod | client registration | client_secret, private_key_jwt, tls_client_auth, self_signed_tls_client_auth, none. Immutable after creation |
dpopBoundAccessTokens, certificateBoundAccessTokens | client registration | boolean, never defaulted |
requirePushedAuthorizationRequests | client registration | boolean, never defaulted |
applicationType | client registration | web, native |
See the Central API specification for the full request shapes.
What this is not
A security profile is a set of checks that Versola applies. It is not a certification yet. Versola has not been through OpenID Foundation conformance testing for FAPI 2.0, and nothing on this page claims a conformance result. We plan to go through the certification. For the FAPI 2.0 requirements Versola implements, see the standards checklist for FAPI 2.0.