Control access

Two-factor authentication

Anyone can turn on a second sign-in step for their own account under Profile → Two-factor authentication. They can use either or both of:

  • An authenticator app. Google Authenticator, 1Password, Authy, or any app that reads an otpauth:// QR code: 6 digits, 30 seconds, SHA-1.
  • Passkeys and security keys. WebAuthn covers platform passkeys such as Touch ID, Windows Hello, or a phone, and hardware keys such as a YubiKey.

Adding the first factor also mints ten recovery codes. They are shown once, and each signs in once. Regenerating them from the same dialog invalidates every old code.

It is opt-in per person. An organization administrator cannot require it, and cannot see or reset another member's factors.

What it covers

Only the web sign-in. Connector tokens are not affected. An MCP token is a credential in its own right, and Claude cannot answer a second-factor prompt. To cut off a leaked token, rotate or revoke it from its connection's page. See Tokens and permissions.

A passkey is only a second factor. You still type your password first; there is no passwordless sign-in.

How sign-in works

Password first

Email and password, as before. If they are right and the account has a factor, no session starts yet. The browser gets a five-minute, HTTP-only cookie scoped to the login route. An account has one pending sign-in at a time; entering the password again cancels the earlier one.

Then a factor

The person answers with an authenticator code, a passkey, or a recovery code. A right answer starts the normal session. Each answer uses one of five attempts as it arrives, before it is checked, so sending many at once gets no more than five. After that, the password has to be entered again.

Each authenticator code works once, so a code seen over someone's shoulder cannot be replayed. Throttles refuse further attempts for a while after ten failures in fifteen minutes: per account for the second step, and per email and per client address for the password. They are kept in memory, per process.

Adding or removing a factor, or regenerating recovery codes, asks for the current password. Turning two-factor on signs out every other session of that account.

Passkeys and the app URL

A passkey is bound to a domain. Automata takes that domain from NUXT_PUBLIC_APP_URL, never from the request, so:

  • NUXT_PUBLIC_APP_URL must be the address people actually open. If it is wrong, the browser refuses the passkey prompt. If it is unset, passkeys are hidden and the settings say why. Authenticator apps still work.
  • Moving to another domain makes every registered passkey unusable. Authenticator apps and recovery codes are unaffected. Before a domain move, make sure people have one of those, or warn them to re-add their passkeys.
  • Browsers allow WebAuthn only on HTTPS or localhost. Plain HTTP on a LAN address does not offer passkeys.

Recovering a lost factor

There is no self-service or administrator reset. An operator with database access can turn two-factor off for one account; the person can then sign in with their password and enroll again:

BEGIN;
DELETE FROM app.totp_credentials     WHERE user_id = (SELECT id FROM app.users WHERE email = 'person@example.com');
DELETE FROM app.webauthn_credentials WHERE user_id = (SELECT id FROM app.users WHERE email = 'person@example.com');
DELETE FROM app.recovery_codes       WHERE user_id = (SELECT id FROM app.users WHERE email = 'person@example.com');
COMMIT;

Storage

TableHolds
totp_credentialsThe authenticator secret, the last step a code was accepted for, and confirmed_at
webauthn_credentialsCredential ID, public key, signature counter, transports, name, and last_used_at
recovery_codesSHA-256 of each code and used_at
mfa_challengesPending sign-ins and passkey registrations, short-lived

Authenticator secrets are not encrypted, like the connection credentials in the app schema. Someone holding a database backup can generate codes, but still needs the password, which is stored only as an scrypt hash. Passkey public keys are not secret.

View source