Organisation security policies
Per-organisation MFA, password, and session policies with tenant inheritance and nested org cascades
Wocha lets you define security policies at the tenant level and override them per organisation. Organisations inherit tenant defaults by default and can override individual fields to be stricter — never less strict than the tenant baseline (except when both tenant and org are optional for MFA enforcement).
This guide covers the policy model, inheritance behaviour, Console configuration, and programmatic management via the Customer API.
Overview
The org security policy system covers three policy domains:
| Domain | What it controls |
|---|---|
| MFA | Enforcement level (optional / recommended / required), challenge policy (never / adaptive / always), allowed factors, preferred factor, grace period, unenrolled user action |
| Password | Minimum length, complexity rules, HIBP breach check, maximum age, reuse prevention |
| Session | Absolute session timeout and idle timeout |
Policies are stored in org_security_policies (per-org overrides) and tenant_configs (tenant MFA and password defaults). Legacy org metadata in org_metadata (mfa_enforcement, session_timeout_minutes) is merged during resolution.
At consent time, Wocha resolves the effective policy for the active organisation and enforces MFA, session limits, and password age before issuing tokens.
Policy inheritance model
Resolution follows a strictness merge: stricter wins.
- Start with tenant MFA and password defaults.
- Apply parent organisation overrides (root-first, nearest parent last) when the org is nested.
- Apply this organisation's overrides.
- Return the merged effective policy.
| Field type | Merge rule |
|---|---|
| MFA enforcement | required > recommended > optional |
| MFA policy | always > adaptive > never |
| Allowed factors | Intersection with tenant-allowed factors |
| Grace period | Minimum of tenant and org values |
| Unenrolled user action | force_enrollment > email_challenge > allow |
| Password fields | Org non-null values override tenant; null inherits |
| Session timeout | Org value when set; otherwise tenant/org metadata default |
An organisation cannot set a weaker MFA enforcement or policy than its tenant. The Customer API rejects invalid updates with a validation_error.
MFA policy at org level
Enforcement levels
| Level | Behaviour |
|---|---|
optional | MFA only when tenant policy, adaptive risk, or org mfaPolicy override requires it. Org can still restrict allowed factors. |
recommended | Unenrolled users see an interstitial (/mfa-recommended) with "Set up now" and "Skip for now". Dismissal suppresses the prompt for 7 days. Enrolled users at AAL1 are stepped up. |
required | All members must complete MFA before consent — no grace period. |
MFA policy override
Separate from enforcement, mfaPolicy controls when to challenge:
| Policy | Behaviour |
|---|---|
never | Risk engine and tenant policy do not force MFA (org required enforcement still applies). |
adaptive | MFA when risk verdict is step_up. |
always | Every first-party consent requires MFA for enrolled users. |
Example: tenant adaptive + org always + org required → all org members always face MFA.
Per-org factor configuration
Orgs can override allowedFactors and preferredFactor. Allowed factors must be a subset of the tenant's allowed factors. When adaptive MFA triggers step-up for an org member, the org's factor configuration is used.
See Adaptive MFA for the full risk engine and assessor reference.
Password policy per org
Password policies are enforced at:
- Kratos proxy — registration and settings flows (password change)
- Platform API — API-created users via
validatePassword() - Consent processor — password age expiry redirects to
/settings
| Field | Description |
|---|---|
passwordMinLength | 8–128 characters |
passwordRequireUppercase | At least one uppercase letter |
passwordRequireLowercase | At least one lowercase letter |
passwordRequireNumber | At least one digit |
passwordRequireSymbol | At least one symbol |
passwordHibpCheck | Reject passwords found in Have I Been Pwned (k-anonymity API) |
passwordMaxAgeDays | Force password rotation after N days (0 = no expiry) |
passwordDisallowReuse | Reject passwords matching the last N stored hashes (0 = disabled) |
Org password rules can only be stricter than the tenant default (e.g. longer minimum length, shorter max age).
Session timeout per org
| Field | Description |
|---|---|
sessionTimeoutMinutes | Maximum session lifetime from authenticated_at (minimum 5 minutes) |
sessionIdleTimeoutMinutes | Maximum idle time from last consent activity (minimum 1 minute) |
When either limit is exceeded at consent time, the user is redirected to re-authenticate. OAuth access token TTL is aligned to min(default_ttl, org_session_timeout) so tokens do not outlive the session policy.
Configuration via Console
Navigate to Organisations → [Organisation] → Security to manage the full security policy.
Each field supports an inherit / override pattern:
- Inherited — uses the tenant (or parent org) value; shown as "Inherited from tenant: [value]"
- Customise — toggle to set an org-specific override
- Badge — "Inherited", "Overridden", or "Stricter than tenant"
The Security tab includes:
- MFA Enforcement — optional / recommended / required
- MFA Policy Override — inherit / never / adaptive / always
- Allowed Factors — checkboxes with inherit toggle
- Preferred Factor — dropdown with inherit toggle
- Unenrolled User Action — inherit or override
- Password Policy — min length, complexity, HIBP, max age, reuse prevention
- Session Policy — absolute and idle timeouts
For nested organisations, the UI shows the policy hierarchy: global default → tenant → parent organisation → this organisation.
Tenant-wide password defaults are configured under Settings → Security → Password Policy.
Configuration via Customer API
Organisation security policy
Tenant password policy
Full request and response schemas are documented in the Organisation security policy API reference.
Nested org inheritance
Wocha supports nested organisation hierarchies (parent/child orgs via SpiceDB). Child organisations inherit policies from their parent chain in addition to the tenant baseline.
This is a unique advantage over platforms with flat org models (e.g. Kinde), where policies apply only at a single org level without parent-to-child cascade.
Resolved policies are cached in Valkey for 60 seconds to avoid expensive hierarchy walks on every consent.
Related
- Adaptive MFA — risk engine, assessors, and per-org MFA overrides
- Organisation security policy API — Customer API reference
- Step-up authentication — ACR levels and MFA step-up flows
- Security overview — platform security posture