Skip to content

fix(auth)!: resolve second factor when reauthenticating MFA users - #1419

Draft
demolaf wants to merge 2 commits into
mainfrom
fix/mfa-reauth
Draft

demolaf wants to merge 2 commits into
mainfrom
fix/mfa-reauth

Conversation

@demolaf

@demolaf demolaf commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Resolves the second factor when reauthenticating an MFA-enrolled user. Previously tapping Confirm in the reauth sheet did nothing visible, because the secondFactorRequired error was reported to an alert behind the sheet.

⚠️ Breaking Changes

  • Adds AuthServiceError.multiFactorReauthenticationRequired(MFARequired), so exhaustive switches over AuthServiceError need a new case. reauthenticate(with:) and reauthenticate(context:) throw it instead of the raw secondFactorRequired error.

Changes

  • AuthService keeps the MultiFactorResolver from reauthentication, so resolveSmsChallenge and resolveSignIn complete it as they do for sign-in.
  • Email, phone and email link reauth sheets push MFAResolutionView inside the sheet, and OAuth reauth presents it in its own sheet.
  • Reauth sheets show errors in place, and MFAResolutionView gains a keyboard Done button so the number pad no longer hides its actions.
  • Swiping away any reauth sheet now cancels reauthentication instead of leaving the caller waiting, and signOut() clears the stored MFA resolver.
  • New emulator integration test enrols an SMS factor and asserts the new error. resolveSignIn itself is not asserted because the emulator rejects it (MFA_ENROLLMENT_NOT_FOUND on MFA when using Firebase Auth Emulator firebase-ios-sdk#11079).

Preview

Expected: when a user wants to remove a second factor and is asked to reauthenticate, entering the correct password should take them to the second-factor step so they can finish confirming it is them.

Before (main): nothing happens.

mfa-reauth-before.mp4

After (this branch): the second-factor step opens in the sheet.

mfa-reauth-after.mp4

Maintainer note: Fixes internal CPRN-593

Reauthenticating a user with enrolled second factors threw
secondFactorRequired from user.reauthenticate(with:). The reauth views
passed it to reportError, whose alert sits behind the reauth sheet, so
tapping Confirm did nothing visible.

AuthService now catches secondFactorRequired during reauthentication,
keeps the MultiFactorResolver and throws
AuthServiceError.multiFactorReauthenticationRequired(MFARequired), so
the factor is resolved with resolveSmsChallenge and resolveSignIn as
for sign-in. The email, phone and email link reauth sheets push
MFAResolutionView inside the sheet, OAuth reauth presents it in its own
sheet, and reauth sheets show errors in place instead of behind the
sheet.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for Multi-Factor Authentication (MFA) during reauthentication in FirebaseAuthSwiftUI by introducing a new multiFactorReauthenticationRequired error, updating AuthService to capture the MFA resolver, and integrating the MFA resolution flow into the reauthentication views and coordinator. Feedback on these changes highlights a compiler error in AuthService.swift due to incorrect pattern matching on an existential Error type, a potential leak of CheckedContinuation when other reauthentication sheets are dismissed without onDismiss handlers, and a potential memory leak of MultiFactorResolver if the MFA flow is cancelled or fails without clearing currentMFAResolver.

@demolaf demolaf changed the title fix(auth): resolve second factor when reauthenticating MFA users fix(auth)!: resolve second factor when reauthenticating MFA users Oct 22, 2026
@demolaf
demolaf marked this pull request as draft October 22, 2026 09:52
The phone, email and email link reauth sheets had no onDismiss, so
swiping one away left the requestReauth continuation pending and the
caller waiting forever. They now cancel reauthentication on dismiss,
as the MFA reauth sheet already does. signOut also clears any stored
MFA resolver so it does not outlive the session.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant