fix(mfa): hard-navigate after TOTP enrolment so the user is not stranded on the QR screen (#1948) (#1984)
leave() in /mfa/enroll ended with router.push(returnTo) followed by router.refresh(). Enrolling raises the session to aal2, which lib/supabase/middleware.ts only re-evaluates on a fresh document request; the push and the refresh raced, the refresh won, and the user was left on the QR screen with 2FA already active and no way forward but the address bar. Always window.location.assign(returnTo) instead, the way the same function already did for /api/ destinations and /mfa/verify does for its invite and route-handler paths. returnTo is already validated by safeReturnTo, so the unconditional hard navigation stays same-origin. Claude-Session: https://claude.ai/code/session_01FkUfWtuFCUkNtRAgMQCse2 Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
fca57dc470
commit
04406edb0f
@@ -37,16 +37,16 @@ function MfaEnrollContent() {
|
||||
|
||||
const returnTo = safeReturnTo(searchParams.get('returnTo'), '/')
|
||||
|
||||
// Always a hard navigation, for two reasons that point the same way.
|
||||
// Route-handler destinations (the MCP OAuth consent page sends new
|
||||
// password accounts here with returnTo=/api/mcp-oauth/authorize…) return
|
||||
// raw HTML the client router cannot render: hard-navigate, like /mfa/verify.
|
||||
// password accounts here with returnTo=/api/mcp-oauth/authorize...) return
|
||||
// raw HTML the client router cannot render. And enrolling raises the
|
||||
// session to aal2, which lib/supabase/middleware.ts only re-evaluates on a
|
||||
// fresh document request: `router.push` followed by `router.refresh` raced,
|
||||
// the refresh won, and the user was left on the QR screen with 2FA already
|
||||
// active and no way forward but the address bar (#1948).
|
||||
const leave = () => {
|
||||
if (returnTo.startsWith('/api/')) {
|
||||
window.location.assign(returnTo)
|
||||
return
|
||||
}
|
||||
router.push(returnTo)
|
||||
router.refresh()
|
||||
window.location.assign(returnTo)
|
||||
}
|
||||
// Back must not bounce into the consent page: with no factor enrolled it
|
||||
// redirects straight back here. Abort the connect flow to the app instead.
|
||||
|
||||
Reference in New Issue
Block a user