docs: trusted devices & MFA improvements (design + API/security/schema)

Add TRUSTED_DEVICES_MFA.md (the approved design/implementation plan) and fold
the feature into BACKEND_DESIGN §3 (trusted_devices + recovery_codes schema),
§4 (login/totp trust+recovery, /auth/me/trusted-devices*, recovery-codes*,
admin trusted-device + /mfa/reset routes), and §6 (trusted-device security
model + audit actions). Note the app-side trust/recovery flow in android PLAN §4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 23:39:05 -05:00
parent e82eac6d97
commit 6e7da3acbe
3 changed files with 267 additions and 4 deletions

View File

@@ -543,6 +543,27 @@ Uses the existing **mobile bearer** surface, no backend changes:
`401` from a bearer call, with a mutex so concurrent 401s trigger only one refresh.
- `POST /auth/mobile/logout` `{ refreshToken?, all? }` (requires bearer) — revoke this session or all
sessions. Called on user logout and on "sign out everywhere."
#### 4.1.1 Trusted devices & recovery codes — backend ready, app work sequenced after backend
The backend trusted-device + recovery-code feature (canonical ref: `../website/TRUSTED_DEVICES_MFA.md`)
is additive on the mobile surface; the app consumes it as follows (implemented **after** the backend
lands, alongside the account screens):
- **Login extras:** `POST /auth/mobile/login` accepts `recoveryCode` (a single-use alternative to
`code`), `trustDevice: true`, and an `X-Trust-Token` header. On the `401 { totpRequired }` screen,
offer "use a recovery code instead" and a **"Trust this device"** checkbox. When `trustDevice` is set
and accepted, the response carries `trustToken` → **store it in EncryptedSharedPreferences** (same
store as the bearer tokens, never plain prefs/logs) and send it as `X-Trust-Token` on future logins
to skip the TOTP prompt. A `{ trustLimitReached, devices }` response means show the device list and
prompt the user to revoke one (`DELETE /auth/me/trusted-devices/:id`) then retry.
- **Self-service (account screens):** `GET /auth/me/trusted-devices`, `DELETE …/:id`, `DELETE
…/trusted-devices` (untrust all); `POST /auth/me/trusted-devices` to trust the current device from an
authenticated session (returns `{ trustToken }` for native). Recovery codes: enabling TOTP returns
the one-time `recoveryCodes` (show once, offer copy/share); `GET …/recovery-codes/status` for the
remaining count; `POST …/recovery-codes/generate` (password step-up) to regenerate.
- **Invalidation:** on logout / dead-refresh sign-out / Settings→Server switch, **clear the stored
`trustToken`** along with the bearer tokens (a password change/reset or TOTP disable already revokes
it server-side).
### 4.2 Website-handled flows: registration, invite, forgot-password, SSO
These are **not** rebuilt in the app. The app links out to the website's own pages/API and the user
completes them in a Custom Tab, then returns and signs in natively (§4.1):