Skip to main content

Session policy

A session policy belongs to a team. Every authenticated request is checked against the policies of all the teams the caller belongs to, before any handler runs. Someone in several teams gets the strictest combination: the shortest timeouts, every allowlist, the smallest session cap, and MFA if any team requires it.

Rules

An ended session answers 401 with session_idle_timeout or session_max_lifetime and is revoked, so the dashboard returns to the sign-in page. These rules sit on top of APP_SESSION_TTL and APP_AUTH_ENGINE_SESSION_IDLE_TIMEOUT from Sign-in engine; whichever is shorter wins. If the policy cannot be read, requests are refused with 503 rather than let through.

Configure

Open Settings, Session policy, choose Edit policy on a team, and save. Or:
set replaces the whole policy: a rule you leave out is turned off. Every user is a member of the default team (org_default), so its policy is effectively instance-wide.

Lockout protection

Saving is refused when the new policy would block the admin saving it: your own current address must be allowed, and you must have a second factor before requiring one. Your address at the top of the page is the address the server sees. Behind a reverse proxy, the address comes from X-Forwarded-For only when the TCP peer is loopback or listed in APP_INGRESS_TRUSTED_PROXIES. Otherwise the peer address is used and forwarded headers are ignored, so a client cannot spoof its way into an allowlist.

Recovering from a lockout

If an allowlist or MFA requirement locks everyone out, remove every session policy from the host. This opens the data directory directly, so it works without network access to the API, and it is written to the audit log:
Then sign in again. recover-admin still resets an admin password, and emergency-token still mints a root token, but that token is subject to the allowlist like any other, so run access-policy-reset first if your address is blocked. See Emergency access.

Things to know

  • Existing API tokens keep working without MFA; the MFA rule applies to dashboard sessions. Tokens are still bound by the allowlist.
  • The session cap is enforced by the API middleware, not by the sign-in library: the library’s own cap is a single global value and cannot differ per team. A new session is checked on its first request after sign-in or the two-factor step, so the sign-in itself succeeds and that first request is refused. Sessions already inside the cap are re-checked every 30 seconds. If sessions cannot be listed, the request is refused with 503.
  • Pending two-factor sessions do not count towards the cap, only fully signed-in ones.
  • Idle time is tracked to about 30 seconds of precision.
  • Removing a user from a team removes that team’s rules for them at their next request.

API

The body of a PUT is {"idle_timeout": "30m", "max_lifetime": "12h", "ip_allowlist": ["203.0.113.0/24"], "require_mfa": true, "max_concurrent_sessions": 3, "on_limit": "evict_oldest"}. on_limit is evict_oldest (default) or reject.
Last modified on October 15, 2026