A tenant's authentication policy is the configured set of rules that decide:
- Which authentication methods can be used (password, social, SAML, magic link, etc.).
- When MFA is required, optional, or never asked for.
- What the minimum authentication level (AAL) is for various flows.
- How long sessions live before they require re-auth.
Your code doesn't write the policy — that's a tenant admin's job. But the policy affects what your SDK calls return + which errors you handle. Worth knowing the shape so you can predict the behaviour.
What the policy controls
Section titled “What the policy controls”Five major decisions tenant admins make:
1. Allowed authentication methods
Section titled “1. Allowed authentication methods”Which factors are even enabled on this tenant? Options:
- Email + password.
- Magic link (passwordless email).
- Social federation (Google, GitHub, Microsoft, Apple, etc.).
- SAML federation (Okta, Entra, OneLogin, etc.).
- WebAuthn / passkeys (primary factor, not just second factor).
Tenant admins enable the subset their product needs. End-users see only enabled methods on the login surface.
2. MFA enforcement
Section titled “2. MFA enforcement”Three modes:
- Off. No MFA at any time. Suitable for low-value apps or specific tenant tiers; rare for production tenants.
- Optional. Users can enrol MFA voluntarily. The platform never refuses sign-in for missing MFA.
- Required. Every user must enrol MFA before they can sign in. Stricter; common in B2B.
If MFA is required and the user hasn't enrolled, the sign-in flow forces enrolment as part of the flow. Your SDK calls don't have to do anything special — the redirect-based flow handles it.
3. Step-up policy
Section titled “3. Step-up policy”For high-value actions, the tenant can require a fresh MFA challenge even on already-MFA'd sessions. Configurable per:
- Scope — e.g. requesting
admin:writetriggers step-up. - Endpoint — your backend marks specific routes as requiring step-up.
- Risk score — adaptive (see below).
The step-up flow is documented in Step-up authentication.
4. Session lifetime
Section titled “4. Session lifetime”How long a session stays valid before requiring re-auth. Two relevant settings:
- Inactivity timeout. Session expires after N minutes/hours of no activity. Typical: 30 min for high-security, 8 hrs for normal, 30 days for "remember me".
- Absolute timeout. Session expires N minutes/hours/days after sign-in regardless of activity. Caps the maximum session age.
When the session expires, the next API call your SDK makes returns session_expired; the SDK surfaces this to your code so you can route the user back to sign-in.
5. Adaptive / risk-based
Section titled “5. Adaptive / risk-based”If the platform's risk engine is enabled on this tenant, the policy can include rules like:
- Bump to AAL2 if the IP is on a denylist, or the device is unrecognised, or the user travelled impossibly far since the last sign-in.
- Trigger a CAPTCHA if the failed-login rate from this IP is above a threshold.
- Deny outright if the IP is on a Tor exit node list (your tenant might be strict).
These rules run during sign-in + token-refresh; if the risk engine flags a request, the SDK surfaces a risk_challenge error that your code handles.
See Risk and adaptive authentication.
What you (developer) need to handle
Section titled “What you (developer) need to handle”For your code, the policy mostly translates into "which errors might come back from the SDK." A defensive integration handles all of:
mfa_required— open the MFA challenge UI.mfa_enrolment_required— open the MFA enrolment flow.session_expired— redirect to sign-in.consent_required— open the consent screen.risk_challenge— render the CAPTCHA or challenge.insufficient_auth_level(from your own API) — trigger step-up.
The React SDK exposes all of these as error.code values on the useIntelliAuth() error state. Branch on error.code (stable strings) rather than message text (varies).
Reading the policy from code
Section titled “Reading the policy from code”You usually don't need to. The policy is server-enforced; your code reacts to the outcomes. If you genuinely need to read the policy (e.g., to show a "MFA is required at your organisation" banner), the management client exposes mgmt.tenants.getAuthPolicy() which returns the current policy as JSON.