Skip to content

Two-factor sign-in (TOTP)

Accounts that sign in to CertIntel with a password can add a second step: a 6-digit code from an authenticator app (TOTP, RFC 6238), such as Microsoft Authenticator, Google Authenticator, 1Password or Bitwarden. Each person sets it up for their own account; an administrator can make it required for the whole workspace. It is available on every plan.

Two-factor sign-in applies to local password accounts only:

Not affected Why
Single sign-on (OIDC) accounts The identity provider signs them in and is responsible for their second factor. Enforce MFA there; see SSO overview.
Demo accounts They cannot set it up.
API keys A key is its own credential and never asks for a code; see API keys.
Platform impersonation and act-as sessions They start from an already signed-in operator.

Setting it up

  1. Open the account menu and choose Account security (/account/security).
  2. Choose Set up two-factor sign-in.
  3. Scan the QR code with your authenticator app. If you cannot scan it, copy the key under Can't scan it? Enter this key instead, or the Setup link (otpauth://); both have a Copy button.
  4. Enter the 6-digit code the app shows and choose Turn on two-factor sign-in. Nothing changes until a correct code confirms the setup; Start again with a new key discards the unconfirmed key.
  5. Save the recovery codes shown next, then choose I have saved them.

Turning it on signs you out of every other session; the session you used stays signed in.

Recovery codes

You get 10 recovery codes in the form XXXXX-XXXXX. They are shown once, right after setup, and each one signs you in once instead of a code from the app. Account security shows how many remain. Make new recovery codes (it asks for a code from the app) replaces all of them; the earlier codes stop working. CertIntel stores only a keyed hash of each code.

Signing in

After your email and password, the Two-factor sign-in page asks for the Code from your authenticator app. The code changes every 30 seconds; a code is accepted for one step either side of the current one, and each code works only once. Use a recovery code instead takes a recovery code. Cancel and sign out abandons the sign-in.

Until the code is verified, the password alone gives access to nothing else: the half-finished sign-in expires after 10 minutes. After verifying, you continue where you were going, including a workspace sign-in handoff and a forced password change.

Limits and lockout

  • Five code attempts per account within five minutes; further attempts are refused until the window passes.
  • Ten failed attempts in a row lock sign-in to the account for 15 minutes and end all of its sessions.
  • For an account with two-factor sign-in, a correct password alone no longer clears the count of failed attempts; only a verified code does.

Failed codes are recorded in the activity log and raise the auth.warning alert like failed passwords.

Turning it off or changing your authenticator

Under Account security, Turn off two-factor sign-in needs a current code or a recovery code. It is not available while the workspace requires two-factor sign-in.

There is no separate "change authenticator" step yet: turn two-factor sign-in off and set it up again with the new app. Under a required policy that means asking an administrator to reset it.

Workspace policy

Holders of security.update (tenant administrators, or a workspace-wide custom role) set the policy under Security → Two-factor sign-in:

  • Optional (the default) - anyone with a password can turn it on for their own account.
  • Required - everyone with a password must set it up. Nobody can turn it off for themselves.

Grace period (days) is 0–30, default 7. It counts from when the policy became required, or from when an account was created if that is later; 0 means straight away. During the grace period, accounts without two-factor sign-in see a reminder banner with the deadline. After it, a local account without two-factor sign-in can only reach Account security until it sets it up, and its API calls are refused with 403 and the problem type mfa-required.

Administrator reset

When someone has lost both their authenticator and their recovery codes, an administrator can remove their second factor:

  • Users → Manage → Reset two-factor, which needs users.update for that user and follows the same rules as a password reset (see who can manage whom). It is refused while acting as another user.
  • POST /api/v1/users/{user_id}/mfa/reset, which answers 204.
  • On the platform console, Reset two-factor on the tenant's user list.

The reset signs the user out everywhere. They sign in with their password and can set it up again; under a required policy whose grace period has passed, they are asked to do so at once. You cannot reset your own two-factor sign-in this way (409); use Account security. The Users list marks accounts that use it with a 2FA pill.

API sign-in

POST /api/v1/auth/login answers with mfa_required. When it is true, the session cookie it set allows only these calls until the second step succeeds:

Call Result
POST /api/v1/auth/mfa/verify with {"code": "123456"} or {"recovery_code": "XXXXX-XXXXX"} 200 with the signed-in principal and a new session cookie; 401 for a wrong code, 429 when rate-limited, 409 when no sign-in is waiting for a code.
GET /api/v1/auth/me, POST /api/v1/auth/logout As usual.

Every other call answers 403 with mfa-required. Setting up two-factor sign-in has no API; it is done in the dashboard. Automation should use an API key, which two-factor sign-in does not affect.

Activity log

Setup, turning off, verified and failed codes, a used recovery code, new recovery codes, an administrator reset and policy changes are recorded as auth.mfa.enrolled, auth.mfa.disabled, auth.mfa.verified, auth.mfa.failed, auth.mfa.recovery_used, auth.mfa.recovery_regenerated, auth.mfa.reset and tenant.mfa_policy_updated.

Self-hosted settings

Setting Default Meaning
CERTINTEL_MFA_ISSUER CertIntel The issuer name the authenticator app shows.
CERTINTEL_MFA_PENDING_SESSION_SECONDS 600 How long a sign-in may wait for its code.
CERTINTEL_MFA_MAX_ATTEMPTS 5 Code attempts per account within the window below.
CERTINTEL_MFA_ATTEMPT_WINDOW_SECONDS 300 The attempt window.