Skip to content

linkWithPopup throws auth/multi-factor-auth-required after successful link, getMultiFactorResolver fails with auth/argument-error #9467

@wadim-pi

Description

@wadim-pi

Operating System

macOS (26.2 (25C56))

Environment (if applicable)

Safari (Version 26.2 (21623.1.14.11.9))

Firebase SDK Version

Tested on both 12.6.0 and 12.8.0 - same behavior

Firebase SDK Product(s)

Auth

Project Tooling

React SPA with Vite

Detailed Problem Description

What I was trying to achieve

Link a federated provider (Microsoft) to an existing user account that has Phone MFA enabled, using linkWithPopup().

What actually happened

  1. linkWithPopup() throws auth/multi-factor-auth-required error
  2. Attempting to handle the error with getMultiFactorResolver(auth, error) fails with auth/argument-error
  3. However, checking currentUser.providerData reveals the provider WAS successfully linked

Console output (Firebase 12.8.0)

  Error code: auth/multi-factor-auth-required                                                                           
  Error customData: {_serverResponse: Object, appName: "[DEFAULT]"}                                                     
  Error serverResponse: {                                                                                               
    federatedId: "http://microsoft.com/...",                                                                            
    providerId: "microsoft.com",                                                                                        
    email: "user@example.com",                                                                                          
    emailVerified: true                                                                                                 
  }                                                                                                                     
  getMultiFactorResolver FAILED: "auth/argument-error"                                                                  
  Provider IDs after reload: ["microsoft.com", "password"]                                                              
  Was linked: true

Key observations

  • The _serverResponse contains the successfully linked federated identity, confirming the link completed on the
    server
  • The error doesn't contain valid MFA resolver information (hence getMultiFactorResolver fails)
  • Same behavior on both 12.6.0 and 12.8.0

Expected behavior

Either:

  1. linkWithPopup() should resolve successfully since the link completes, OR
  2. If MFA verification is required, the error should contain valid resolver information

Current workaround

We reload the user and check if the provider was linked. This is brittle - if Firebase changes timing (throws error
before link completes), it would break.

Related

"properly propagate the FirebaseAuthMultiFactorException for all reauthenticate and link methods"

Additional context

  • Tested on localhost (127.0.0.1) development environment
  • Not yet verified if the issue reproduces on production domains

Steps and code to reproduce issue

  // Prerequisites:                                                                                                     
  // 1. User account with email/password + Phone MFA enabled                                                            
  // 2. User is signed in and has completed MFA verification                                                            
                                                                                                                        
  import { getAuth, getMultiFactorResolver, OAuthProvider, linkWithPopup } from 'firebase/auth';                        
                                                                                                                        
  const auth = getAuth();                                                                                               
  const currentUser = auth.currentUser;                                                                                 
  const provider = new OAuthProvider('microsoft.com');                                                                  
                                                                                                                        
  try {                                                                                                                 
    await linkWithPopup(currentUser, provider);                                                                         
    console.log('Link succeeded');                                                                                      
  } catch (error) {                                                                                                     
    console.log('Error code:', error.code);                                                                             
    // Output: "auth/multi-factor-auth-required"                                                                        
                                                                                                                        
    // Attempting to handle MFA as documented                                                                           
    try {                                                                                                               
      const resolver = getMultiFactorResolver(auth, error);                                                             
      console.log('Resolver:', resolver);                                                                               
    } catch (mfaError) {                                                                                                
      console.log('getMultiFactorResolver failed:', mfaError.code);                                                     
      // Output: "auth/argument-error"                                                                                  
    }                                                                                                                   
                                                                                                                        
    // Check if link actually succeeded despite the error                                                               
    await currentUser.reload();                                                                                         
    console.log('Provider IDs:', currentUser.providerData.map(p => p.providerId));                                      
    // Output: ["microsoft.com", "password"] - link DID succeed!                                                        
  }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions