# Two-factor authentication (TOTP)

ActivityLog supports time-based one-time passwords (TOTP) for portal sign-in. This is the same standard used by Google Authenticator, 1Password, Authy, Microsoft Authenticator, and every other TOTP app.

## When TOTP is required

| Account type | TOTP behavior |
|---|---|
| **Customer user** (`member`, `admin`, `owner` on a tenant) | Optional. Enable from your profile page. |
| **Fyin operator** (platform-admin role on `/portal/admin/`) | **Mandatory.** A 7-day grace period applies from first sign-in; after that, sign-in is blocked until TOTP is enrolled. |

This page covers the customer-user flow. Operator TOTP (with per-action re-prompt) is described in [`80-admin-portal.md`](./80-admin-portal.md).

## Enroll TOTP

1. Sidebar → **Profile** → **Security** tab.
2. Click **Enable two-factor**.
3. The portal shows a QR code and a six-digit secret.
4. Scan the QR code with your authenticator app (or type the secret).
5. Enter the current 6-digit code your app shows to confirm.
6. **Save** — TOTP is now active on your account.

![TOTP enrollment screen with QR code](screenshots/portal-totp-enroll.png)

> **Save the backup codes.** Immediately after confirming, the portal shows 10 single-use recovery codes. Store them somewhere safe (1Password, printed copy in a drawer). If you lose your authenticator device these are the only way back in.

![Backup codes display](screenshots/portal-totp-backup-codes.png)

## Sign in with TOTP

After enrollment, sign-in is a two-step flow:

1. Email + password as before.
2. A second screen prompting for the 6-digit code from your authenticator.

If you've enabled "remember this device" the second step is skipped on the same browser for 30 days.

![TOTP code prompt during sign-in](screenshots/portal-totp-signin-prompt.png)

## Remove TOTP

**Profile → Security → Disable two-factor**. You'll be prompted for the current TOTP code one last time to confirm — once submitted, the secret is wiped and sign-in goes back to email + password only.

## Recover when you've lost your authenticator

1. On the TOTP prompt during sign-in, click **Use a backup code**.
2. Enter one of your 10 recovery codes.
3. You're signed in. **Immediately** revisit Profile → Security and either:
   - **Re-enroll TOTP** with a new authenticator (recommended), or
   - **Disable TOTP** if you're going to wait to set it back up.

Once used, a backup code is invalidated. You're down to 9.

If you've lost both the authenticator **and** the backup codes, your tenant `owner` (or, failing that, Fyin support) can reset TOTP on your account from the admin portal — see [`80-admin-portal.md`](./80-admin-portal.md#reset-a-user-s-totp).

## Recommended authenticator apps

| App | Notes |
|---|---|
| **1Password** | Stores TOTP secrets alongside passwords; recovery on device loss is automatic if your 1Password account is healthy. **Recommended.** |
| **Microsoft Authenticator** | If your shop is Microsoft 365, you probably already have this. |
| **Authy** | Multi-device sync built in (controversial but convenient). |
| **Google Authenticator** | Free, simple, no cloud sync until recent versions. |

Avoid SMS-based 2FA — it's not what TOTP uses, and SMS is a known weak factor (SIM-swap attacks).

## Best practices

- **Enroll on day one.** Don't postpone — the cost is 30 seconds.
- **Print or write down your backup codes.** A digital-only copy that's locked behind the same authenticator defeats the purpose.
- **Re-enroll after device migration.** When you swap phones, set up TOTP on the new device before discarding the old one if possible. If not, use a backup code.
- **Don't share your authenticator code.** Anyone who can read your screen at the right moment can sign in as you for 30 seconds.

## What's next

| Goal | Doc |
|---|---|
| Understand the admin (operator) TOTP gating | [`80-admin-portal.md`](./80-admin-portal.md) |
| Send a test message now that you're locked down | [`00-quickstart.md`](./00-quickstart.md) |

## Troubleshooting

**"Invalid code" but my authenticator shows it clearly.**
Clock skew is the usual cause. Make sure your phone's time is set to "Automatic" / network-synced. Codes are valid for 30 seconds with a ±1-window grace (so 60s either side), but a phone whose clock is two minutes off won't work.

**I lost my authenticator AND my backup codes.**
Sign-in is impossible from the customer portal. Contact Fyin support with proof of identity. An operator can reset your TOTP from `/portal/admin/`.

**My "remember this device" cookie expired sooner than 30 days.**
Clearing browser cookies (manual or by a privacy extension) wipes the device-trust cookie. You'll re-prompt for TOTP and a fresh 30-day window starts.
