Authentication security
FlagTGL supports passkeys, authenticator-app MFA, one-time recovery codes, and recent step-up authentication. Every user can manage these controls from Dashboard → Account security.
Security controls available today
Passkeys
Passkeys use WebAuthn and can be backed by Touch ID, Face ID, Windows Hello, Android, or a roaming hardware security key. FlagTGL requests a discoverable credential and requires user verification for registration, sign-in, and step-up ceremonies.
The service stores the credential ID plus an encrypted WebAuthn credential record containing the public key, signature counter, transports, authenticator flags, and attestation data needed for future verification. Private keys never leave the authenticator. WebAuthn challenges expire after five minutes and are deleted when consumed, whether verification succeeds or fails.
A passkey can be used for passwordless sign-in. Accounts with any enrolled factor do not receive an application token after password verification: they must finish MFA with an authenticator code, a recovery code, or a passkey ceremony.
Authenticator-app MFA (TOTP)
FlagTGL supports the standards-based six-digit TOTP format used by common authenticator apps. Enrollment requires the current password. The TOTP secret is encrypted at rest with authenticated AES-GCM, is returned only during enrollment, and is not enabled until a valid code is supplied.
The verifier accepts a narrow clock-skew window and records the last accepted time step. A code from an already accepted time step cannot be replayed. Disabling TOTP requires recent step-up authentication and also revokes its recovery codes.
Recovery codes
Ten recovery codes are generated when TOTP enrollment is confirmed. Plaintext codes are displayed once. Only SHA-256 hashes of the high-entropy codes are stored.
Each code is atomically marked used during verification, so concurrent attempts cannot consume the same code twice. Generating a replacement set immediately deletes every old code. Recovery-code use appears in the security audit trail. Store the plaintext set in a password manager or another protected offline location.
Step-up authentication
Sensitive factor operations require a separate, recent authentication ceremony. If the account has a passkey, the dashboard uses a user-verified passkey ceremony. Otherwise it asks for the current password. The resulting opaque grant:
- is scoped to the current user;
- expires after ten minutes;
- is stored only as a SHA-256 hash;
- cannot be used as an API bearer token; and
- is passed separately in
X-FlagTGL-Step-Upfor protected operations.
Step-up currently protects passkey registration and deletion, TOTP removal, and recovery-code rotation. Additional credential, billing, ownership, export, and destructive organization operations will be moved behind the same middleware as their dashboard flows are updated.
Security audit trail
The Account security dashboard shows the latest 100 factor, MFA login, recovery, passkey, and step-up events. Each record includes:
- the action and authentication method;
- success or failure;
- timestamp;
- source IP; and
- user agent.
The audit writer deliberately never records passwords, TOTP secrets or submitted codes, recovery-code plaintext, WebAuthn challenges or assertion payloads, application tokens, or step-up grants. Failed factor changes are recorded as well as successful ones.
Encryption and key management
TOTP seeds and WebAuthn credential records use AES-GCM with a key derived from FLAGS_CREDENTIAL_ENCRYPTION_KEY. Set a dedicated high-entropy value in every non-development environment, keep it stable across restarts, and back it up in your secret manager. Losing this key makes the protected factor records unusable. Changing it requires a planned re-encryption migration.
Password hashes use bcrypt. Personal API tokens are scoped, expire, are displayed once, and are stored as hashes. Migration-source credentials use the same authenticated encryption boundary as factor secrets.
Important remaining boundaries
The following controls are not yet implemented and FlagTGL should not claim them:
- organization-wide MFA or passkey-only enforcement and enrollment grace periods;
- server-managed browser sessions, device/session inventory, or immediate session revocation (the web client still uses a 24-hour bearer token in local storage);
- dedicated account/IP rate limits for login, signup, TOTP, recovery, and WebAuthn endpoints;
- compromised-password screening, risk-based authentication, or security-event notifications;
- enterprise SSO enforcement and support-assisted account recovery; and
- FIDO Metadata Service trust-policy enforcement for authenticator models.
These boundaries matter. Passkeys and MFA are production features, but they do not by themselves provide a complete enterprise identity-control plane.
Operational verification
Before enabling this release in a new environment:
- Set
FLAGS_BASE_URLto the exact browser origin. WebAuthn validates the relying-party ID and origin, so a mismatched hostname or scheme causes ceremonies to fail safely. - Set and retain
FLAGS_CREDENTIAL_ENCRYPTION_KEYindependently fromFLAGS_JWT_SECRET. - Verify passkey registration and sign-in with a platform authenticator and a roaming security key on the browsers you support.
- Verify TOTP enrollment, code-replay rejection, recovery-code single use, code-set rotation, and factor deletion.
- Confirm failed and successful operations appear in Account security → Security activity and that logs contain no submitted secrets.
- Exercise database backup and restore with the same encryption key before relying on enrolled factors for account access.
Security-sensitive changes should also receive external application-security review, including tests for origin confusion, challenge replay, credential cloning counters, account enumeration, owner lockout, OAuth account linking, and multi-tenant authorization boundaries.