fix(security): revoke other sessions when the second factor is removed

Removing the second factor is a security-state change, so it should not leave
stale credentials behind. The disable endpoint now drops every other web
session, every native refresh token, and every trusted device, keeping only the
caller's current session. The lockout-recovery CLI does the same out of band,
clearing all sessions and trusted devices for the account.
This commit is contained in:
Marc-André Bombeck committed 2026-06-27 21:50:16 +02:00
1 parent 94c3cdea96
commit c44eed365d
3 files changed
+109 -1

No files matched your search

+11
View File
@@ -68,6 +68,17 @@ async function main(): Promise<void> {
},
});
await tx.mfaRecoveryCode.deleteMany({ where: { userId: user.id } });
// v1.23 (M-review L3) — removing the second factor is a security-state
// change. Out-of-band there is no "current" session to keep, so drop every
// session, every native refresh token, and every "remember this device"
// trusted device for the account: a stolen session or trusted-device cookie
// must not survive the lockout-recovery reset.
await tx.session.deleteMany({ where: { userId: user.id } });
await tx.refreshToken.updateMany({
where: { userId: user.id, revokedAt: null },
data: { revokedAt: new Date() },
});
await tx.trustedDevice.deleteMany({ where: { userId: user.id } });
await tx.auditLog.create({
data: {
action: "auth.mfa.disabled",