- Ya
- 3 Agosti 2026, 04:31 UTC
- Mwandishi
- Kamo
- Ahadi ya
- e5efc19
Completes MFA. The core landed in kamo-shared-library; this is the wire that turns stored configuration into an actual gate. The gate is small because login already had the right shape: it creates the *** session and hands it to the client ONLY as a one-time key in the response body — no cookie is set at login. So the entire mechanism is to withhold the OTK until the second factor is proven. A session nobody holds an OTK for is unreachable, which means session creation itself needed no surgery at all. MfaChallengeService holds the ***Id under an opaque, single-use, 5-minute token. The client never receives the session id, and the token is worthless without a code. Short on purpose: a half-authenticated state survives a password compromise. POST /api/security/mfa/challenge completes the login, releasing the OTK so the client resumes exactly the flow it would have had without MFA. A wrong code releases nothing and — deliberately — does NOT burn the challenge, because forcing a user back through the password over one typo is how MFA gets switched off. The enrollment's own lockout counts those failures. A success consumes the challenge so it cannot be replayed. Recovery codes complete it too, and are never also tried as a TOTP. Enrollment endpoints (/enroll, /confirm, /status) require a session — enrolling a factor is an authenticated action on your own account. /challenge deliberately does not, because its caller is mid-login by definition. INERT TODAY: the gate fires only on hasConfirmedFactor, and nobody is enrolled, so the existing login path is byte-identical. That is the point — this can deploy before any client supports it. The endpoint ratchet caught my own three enrollment handlers as unguarded. They are guarded, through a userIdFromSession helper the one-method-deep scan cannot follow, so the fix was teaching GUARD that helper rather than baselining them. I also documented the converse limitation the same exercise exposed: completeChallenge clears the scan only because it happens to touch kSessionService.