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¶
- Open the account menu and choose Account security (
/account/security). - Choose Set up two-factor sign-in.
- 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.
- 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.
- 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.updatefor 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 answers204.- 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. |