Skip to main content
Console identity controls: what a sign-in requires, how long it lasts, and what happens when someone guesses. Everything here is off by default. A gateway upgraded into this release behaves exactly as it did before — 30-day sessions, no lockout, no MFA. This is deliberate: a control that switches itself on with thresholds nobody chose locks operators out of their own gateway during an upgrade, and those are the controls that get switched off permanently. Configure it at Governance → Sign-in Security in the console, or through /api/identity/policy.

Multi-factor authentication

Time-based one-time passwords (RFC 6238) from any authenticator app, plus ten single-use recovery codes.

Enrolling

  1. Open Sign-in Security and choose Set up.
  2. Add the secret to your authenticator app.
  3. Enter the code it shows.
  4. Save the recovery codes. They are displayed once and cannot be retrieved afterwards — only replaced.
MFA is not in force until step 3 succeeds. Abandoning enrolment at the QR code leaves the account exactly as it was, rather than locked behind a secret nobody holds.

Signing in

Enter your username and password as usual. If the account has a second factor, the form asks for a code. A recovery code works in the same field and is consumed when used.
A wrong code counts toward the lockout counter. Without that, an attacker who already has the password gets unlimited guesses at six digits — which falls in hours.

Replay

Each code is accepted once. A code observed in its window — shoulder-surfed, or captured by a phishing page — cannot be presented again. Most TOTP implementations do not do this, and it is the gap between what TOTP is assumed to prevent and what it prevents unaided.

Losing your device

Use a recovery code. If those are gone too, the super-admin can clear the second factor for an account:
This is logged. It is also exactly what an attacker with admin access would do before signing in as someone else, so it is worth alerting on.

Requiring it

require_mfa refuses password sign-in for any console account that has not enrolled. It does not apply to SSO logins — those are authenticated by the identity provider, which is where MFA belongs in that topology. The console refuses to save require_mfa until the caller has enrolled themselves. The alternative is a policy that saves cleanly and locks out everyone including whoever set it.

Session policy

The idle timeout is the one that matters for an unattended browser on a shared machine; an absolute lifetime alone does nothing there. Activity is recorded at most once a minute rather than on every request, so an idle timeout can overshoot by up to that. A write per request would put the sessions table on the critical path of every call the gateway serves. Sessions created before this release have no recorded activity and are given one full idle window from their creation time, rather than being expired the instant the timeout is first enabled. Policy changes reach enforcement within 30 seconds.

Active sessions

Every signed-in browser, with the account, address, client and last activity. Revoke anything unfamiliar; revoking your own signs you out. Sessions carry no token in this view. A session list that included them would hand every caller the credential for each session it shows, and an administrator listing everyone’s would collect the means to impersonate all of them.

Login lockout

A reasonable starting point is 10 failures in 15 minutes, locking for 15 minutes. Lower thresholds turn an ordinary typo into a lockout, and a lockout that hits real administrators during an incident is a control that gets disabled. Locks always expire. An indefinite lock is a denial of service anyone can aim at a named account by typing a wrong password a few times. Counters are kept in the governance store, shared across replicas. An in-process counter is defeated by a restart or a second replica: with N replicas a limit of 5 permits 5N attempts, and nothing shows it happening. Counters are also kept for usernames that do not exist, so a lockout response never reveals whether an account is real. Failed sign-ins are visible on the same page, and an administrator can release an account by hand.

Step-up re-authentication

A session cookie proves someone signed in once, possibly a month ago on a machine they have since walked away from. For most of the console that is the right trade. For the operations that change who can get in, it is not — those are what an attacker holding a stolen cookie reaches for, and each one turns a temporary foothold into a permanent one. Those operations ask for the password again (and a code, if the account has a second factor). One confirmation opens a five-minute window covering all of them. Everything else — providers, virtual keys, teams, guardrails, routing — goes through untouched. That is deliberate: prompting for a password on routine work trains people to type it without reading, and that habit is what a convincing fake login overlay relies on. Those operations are all recorded in the audit chain, and compromising them does not extend the attacker’s access. SSO accounts have no local password. For them the identity provider’s assertion stands as the proof and the window opens without a prompt. That is weaker than the password path; the alternative is issuing a local password to an account whose entire point is not having one. The confirmation is subject to lockout like any other sign-in. Without that, an attacker holding a session would have unlimited guesses at the password with no failed sign-in ever recorded.

Admin IP allowlist

Restricts the console and admin API to given addresses or CIDR blocks. /health and /api/version stay reachable so a load balancer does not take the gateway out of rotation the moment this is enabled.
The address compared is the peer address, not X-Forwarded-For. Trusting a client-supplied header would let anyone bypass the allowlist by sending one.Behind a load balancer every request appears to come from the balancer, so this control does nothing useful in that topology — enforce it at the proxy or the security group instead. Saving an allowlist shows you the address the gateway actually saw; if that is your balancer rather than your own machine, that is the signal.
A malformed entry is rejected rather than silently matching nothing, which would leave the control off while the console still showed it as on.

API

What this does not cover

  • SAML. Only OIDC is implemented for SSO.
  • WebAuthn / hardware keys. TOTP and recovery codes only.
  • Approval / dual-control workflows. No second person has to approve a change; step-up asks the same person again, which is a different control.
  • Per-user policy. One policy for the whole gateway, not per team or role.