Commit Graph
4 Commits
Author SHA1 Message Date
Marc-André Bombeck 7b5bc130d8 fix(auth): require a fresh proof before a second factor is added
A browser session on its own could start TOTP enrollment or register a
security key. Combined with a pending secret counting as a factor, that let
a stolen session give itself a second factor, register a passkey with it,
and keep access after the owner changed the password.

TOTP setup and security-key registration now pass on the cookie path only
when the session signed in or completed a second factor in the last five
minutes, or when the body carries a proof in the step-up shape (password,
a confirmed authenticator code, or a passkey or security-key assertion).
The settings cards ask for that proof when the server answers
auth.reproof.required and retry the same call with it. The Bearer path is
unchanged: its elevation already is the proof.

Every route that checks a password or a factor as a re-proof now uses one
verifier and one per-account budget of five attempts per fifteen minutes,
shared with the step-up mint, and records each refused proof as
auth.mfa.failed. Passkey enrollment and password change had neither the
limit (passkey enrollment) nor the audit row (both). A structural test
freezes the set of credential-verifying routes and requires a throttle and
an audit call in each.
2026-09-26 15:55:57 +02:00
Marc-André Bombeck 12844a9206 test(auth): bind the rotated cookie through its hash after a password change
The assertion compared the cookie to the new session row's id, which only
held while the id WAS the cookie. Check the stored hash instead: it
proves the cookie authenticates the surviving row and that the row id
never reaches the client.
2026-07-19 11:40:56 +02:00
Marc-André Bombeck 1f4ba5939d style: apply prettier across the tree
One-shot prettier pass so the new format:check gate starts from a clean
baseline. Formatting only — no behaviour change. Generator-owned and
vendored artifacts stay untouched via .prettierignore.
2026-06-19 22:20:31 +02:00
Marc-André Bombeck 9715831f82 v1.4.34.5 — audit follow-on: critical-path tests + iOS textarea zoom
Follow-on to v1.4.34.4.

Tests:
  24 new integration tests across 5 files closing the highest
  critical-path gaps the test-coverage audit flagged:
    - auth-password-change.test.ts pins the v1.4.34.3+
      destroyAllSessions three-transport revocation contract.
    - admin-reset-password.test.ts mirrors the same shape for
      admin resets.
    - withings-oauth.test.ts covers connect / callback / disconnect
      + state-token replay rejection.
    - passkey-register.test.ts covers register-options +
      register-verify + tampered-attestation + challenge single-use.
    - cache-invalidation-coverage.test.ts grids the IW-G
      invalidation matrix across 5 write surfaces.
  Integration suite: 197/50 → 222/55. tsc + lint clean.

Mobile:
  Five textareas no longer trigger iOS Safari zoom-on-focus. The
  Coach composer, bug-report description, admin feedback note,
  medication-side-effects notes, and medication-intake JSON
  import all shipped text-sm (14 px). iOS Safari zooms whenever
  an input renders below 16 px. Switched each to
  `text-base sm:text-sm` so mobile clears the floor while desktop
  keeps the compact look.
2026-05-17 00:53:03 +02:00