Files
HealthLog/prisma/migrations/0359_session_reproof_stamp/migration.sql
T
Marc-André Bombeck 0fc83cb0a1 fix(auth): ask for a fresh proof before the record or a credential to it leaves
Exporting the whole record, making a clinician share link, minting a token,
and the admin backup download, upload and restore, data wipe and password
reset ran on a live session alone. The plaintext full backup did, while the
encrypted one beside it asked for a second factor. Whoever held a stolen
session could take the record, or leave behind a credential that outlives
the session.

These now go through one gate, requireRecentProof (assertRecentCookieProof
for the routes that resolve their caller themselves). A browser session
passes after a sign-in or re-proof within five minutes: a second factor on
an account that has one, otherwise the password or a passkey. The refusal is
401 auth.reproof.required with meta.methods, and the web opens the re-proof
dialog, posts the proof to the new POST /api/auth/reproof and retries. A
password proof stamps the new Session.reproofAt (migration 0359), never
mfaVerifiedAt, so it cannot stand in for a second factor anywhere.

On Bearer, the full backup asks for an X-Step-Up elevation; the encrypted
export asks for a second-factor elevation on an account that has one. Share
links and connector tokens keep taking the token alone, because the shipped
app calls them without an elevation and reads a 401 there as a dead
session; the guard test names them.

Key rotation keeps its stricter second-factor gate.
2026-09-26 19:54:38 +02:00

10 lines
604 B
SQL

-- When a browser session last re-proved a credential the account holds.
--
-- Exporting the whole record, making a share link, minting a token and the
-- admin backup / reset / wipe actions now ask for a fresh proof, not just a
-- live session. A second-factor proof keeps stamping `mfa_verified_at`, as it
-- always has. A password proof on an account without a second factor stamps
-- this column instead, so a password never satisfies a gate that asks for a
-- second factor. Nullable, no default: a session that never re-proved has none.
ALTER TABLE "sessions" ADD COLUMN "reproof_at" TIMESTAMP(3);