Govern
Documentation

Version Latest

Sign-in, MFA and passkeys

Password sign-in and password policy, TOTP second factors and recovery codes, passkeys, sessions and token lifetimes, and where Govern asks for a fresh second factor.

This page covers the sign-in methods Govern runs itself. Sign-in through your own identity provider is on Single sign-on with SAML and Single sign-on with OIDC.

Sign-in methods

MethodStatusNotes
Email and passwordWorkingHosted sign-in at /oauth2/authorize; API sign-in at POST /api/v1/auth/login. Passwords are hashed with bcrypt.
TOTP second factorWorkingAuthenticator apps, with one-time recovery codes.
Passkeys (WebAuthn)WorkingRegistration, passwordless sign-in and use as a second factor.
Single sign-onWorkingSAML 2.0 and OpenID Connect connections in Identity Center.
Social sign-inWorkingGoogle, GitHub and Microsoft, per organisation.
Device authorisation grant (RFC 8628)WorkingFor the Neural Inverse apps and CLI on machines without a browser: the app shows a code and the person approves it on the console's device page.
Magic linkPartialThe emailed link does not issue a session. Do not rely on it.

Failed sign-ins answer the same way whether or not the account exists. Brute-force protection runs inside password sign-in, passkey sign-in, the hosted sign-in page, the email routes and root step-up.

Password policy

Each organisation has a password policy, read with GET /api/v1/organizations/{id}/password-policy (organizations:read) and changed with PUT on the same path (organizations:update).

FieldMeaning
min_length, max_lengthLength bounds
require_uppercase, require_lowercase, require_digit, require_specialCharacter classes
history_countHow many previous passwords may not be reused
max_age_daysMaximum password age
lockout_thresholdFailed attempts before lockout
lockout_duration_minutesLockout length

POST /api/v1/auth/password/validate checks a candidate password against the policy without changing anything. People change their own password with POST /api/v1/auth/password/change (the current password is required).

TOTP and recovery codes

A person enrols an authenticator app from their own security page in the console, or through the API:

RoutePurpose
POST /api/v1/users/{id}/totp/enrollReplace any pending factor and return a one-time secret and an otpauth:// URI
POST /api/v1/users/{id}/totp/verifyVerify a six-digit code and turn the factor on
GET /api/v1/users/{id}/totpEnrolment status
DELETE /api/v1/users/{id}/totpTurn the factor off and remove it
POST /api/v1/users/{id}/recovery-codesGenerate recovery codes
GET /api/v1/users/{id}/recovery-codes/countRemaining recovery codes

TOTP secrets are encrypted with AES-256-GCM under the deployment's NI_AUTH_TOTP_ENCRYPTION_KEY. Codes accept one 30-second step of clock skew, and a code that has been used once cannot be replayed.

Passkeys

RoutePurpose
POST /api/v1/passkeys/register/begin, /completeRegister a passkey for the signed-in person; the attestation is verified
GET /api/v1/users/{id}/passkeysList a person's passkeys
PATCH /api/v1/users/{id}/passkeys/{credentialId}Rename one
DELETE /api/v1/users/{id}/passkeys/{credentialId}Delete one
POST /api/v1/auth/passkeys/authenticate/begin, /completePasswordless sign-in, email first

A person manages their own passkeys without any extra permission. An administrator needs users:read to list another person's passkeys, users:update to rename one and users:delete to delete one, and the person must belong to the administrator's organisation (and to no other organisation for a rename or delete). Anyone else gets 404. Administrator actions and refusals are audited (auth.passkey.admin_listed, auth.passkey.renamed, auth.passkey.deleted, auth.passkey.access_denied).

Sessions and tokens

The operator sets session limits with environment variables:

VariableDefaultMeaning
NI_AUTH_ACCESS_TOKEN_TTL15mAccess token lifetime
NI_AUTH_REFRESH_TOKEN_TTL720hRefresh token lifetime (30 days)
NI_AUTH_SESSION_IDLE_TIMEOUT168hA session nobody used for this long ends
NI_AUTH_CONSOLE_SESSION_IDLE_TIMEOUT1hIdle timeout of console sessions
NI_AUTH_CONSOLE_SESSION_MAX_LIFETIME12hAbsolute lifetime of console sessions, at most 12h

Console limits apply to the OAuth client named by NI_AUTH_CONSOLE_CLIENT_ID. Identity Center connections can set their own, shorter limits; see Single sign-on with SAML.

RoutePurpose
POST /api/v1/auth/logoutEnd the current session
POST /api/v1/auth/token/refreshRefresh an access token
POST /api/v1/auth/token/revokeRevoke a token (RFC 7009)
POST /api/v1/auth/token/introspectIntrospect a token (RFC 7662); requires client authentication
POST /api/v1/auth/sessions/revokeEnd one session
POST /api/v1/auth/sessions/revoke-allEnd every session of the caller

Signing out of a session issued through a connection whose identity provider has a logout endpoint answers with an end_session_url, and the client sends the browser there.

Where Govern asks for a fresh second factor

The general step-up authentication package in the source is not mounted, so there is no single step-up setting. These flows ask for a fresh factor themselves:

FlowWhat is required
Activating a just-in-time or break-glass roleA fresh TOTP code in the activation request. See Just-in-time access.
Transferring a verified domain, designating emergency administratorsA session whose MFA is at most 15 minutes old, or an MfaCode in the request (403 STEP_UP_REQUIRED otherwise).
Privileged actions in an SSO sessionRe-authentication at the identity provider when the last authentication is older than the connection's re-authentication window (reauthentication_required).
Owner or Admin actions in an SSO session, when the connection requires identity provider MFAAn authentication that carried the configured amr or acr values (idp_mfa_required).
Root user tasksPOST /api/v1/auth/root/step-up re-authenticates the caller's own login.
Break-glass sign-in while SSO is requiredA TOTP code or passkey after the password, always.

Conditions on role bindings can read request.mfa_age_seconds, but HTTP requests do not report it yet, so a condition that reads it evaluates to an error: a deny that requires recent MFA applies, and an allow that requires it does not grant.

Risk-based sign-in

Risk policies are managed through POST/PUT/DELETE /api/v1/risk/policies* with security:manage and read with security:read; the console shows them read-only on the Security Hub risk policies page. A person may read their own risk history; reading someone else's needs security:investigate.

Last reviewed 17 October 2026View as Markdown

Sign-in, MFA and passkeys · Docs · Neural Inverse