feat(auth): enforced MFA via the session-validation gate (ADR-0069 D3, P1)#2390
Merged
Conversation
…, P1) Completes the session gate (after password expiry #2388) by reusing its authGate seam for enforced MFA. - plugin-auth: computeAuthGate gains an MFA branch — when mfaRequired and the user has no TOTP enrolled (sys_user.two_factor_enabled), block with MFA_REQUIRED once the grace window (mfa_required_at + mfaGracePeriodDays) elapses. mfa_required_at is stamped lazily on first required-but-unenrolled session. isAuthGateActive() also trips on mfaRequired. - bindAuthSettings: mfa_required + mfa_grace_period_days; enabling mfa_required force-enables the twoFactor plugin so /two-factor/* enrollment exists. - platform-objects: sys_user.mfa_required_at column. - service-settings: Multi-factor settings group. Default-off / additive; ADR-0049 (enforcement ships with the setting). Verified live (dogfood): mfa_required + grace 7, un-enrolled user — within grace NOT gated (mfa_required_at stamped); past grace -> 403 MFA_REQUIRED; /two-factor/enable reachable (200, totpURI) while blocked; after enrollment the gate lifts (native 2FA verification takes over); admin within grace NOT blocked. Unit: plugin-auth 191 + service-settings 129 + platform-objects 63 + core 299 + rest 140 green; full build (incl. strict DTS) green. objectui follow-up: Console must render a TOTP-enroll prompt on 403 MFA_REQUIRED. Per-org require_mfa + dispatcher/MCP gate remain follow-ups (#2375). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ADR-0069 P1 (tracking #2281, #2375): enforced MFA (D3) — completes the session-validation gate, reusing the
authGateseam shipped in #2388 (password expiry).What
When
mfa_required(newauthtoggle) is on, an authenticated user without TOTP enrolled is blocked from protected REST resources with403 MFA_REQUIREDonce theirmfa_grace_period_days(default 7) window elapses — while/two-factor/*enrollment stays reachable so they can comply.computeAuthGategains an MFA branch (un-enrolled + grace elapsed →MFA_REQUIRED);mfa_required_at(the grace clock) is stamped lazily on the first required-but-unenrolled session;isAuthGateActive()also trips onmfa_required.mfa_required+mfa_grace_period_days; enablingmfa_requiredforce-enables thetwoFactorplugin so the enrollment endpoints exist (otherwise gated users couldn't comply).sys_user.mfa_required_atcolumn.Default-off / additive; ADR-0049 (enforcement ships with the setting). The
/two-factor/*+change-passwordpaths are already allow-listed by the core gate helper.Verification
mfa_required+ grace 7, un-enrolled user):mfa_required_atstamped)403 MFA_REQUIRED/two-factor/enablereachable (200, totpURI) while blocked — remediation opentwo_factor_enabled) the gate lifts; native better-auth 2FA verification takes overFollow-ups (tracked in #2375)
403 MFA_REQUIRED(otherwise flipping the toggle on shows errors instead of a guided enroll). Backend is default-off so existing envs are unaffected.sys_organization.require_mfa; the dispatcher/MCP gate path.ADR-0069 P1 — now complete
✅ D1 HIBP (#2361) · ✅ D2 lockout+rate-limit (#2365) · ✅ D1 complexity (#2368) · ✅ D1 history (#2371) · ✅ D1 expiry + gate (#2388) · ✅ D3 enforced MFA (this PR).
🤖 Generated with Claude Code