Adding multi-factor authentication to your Android app

This document shows you how to add SMS multi-factor authentication to your Android app.

Multi-factor authentication increases the security of your app. While attackers often compromise passwords and social accounts, intercepting a text message is more difficult.

Before you begin

  1. Enable at least one provider that supports multi-factor authentication. Every provider supports MFA, exceptphone auth, anonymous auth, and Apple Game Center.

  2. Ensure your app is verifying user emails. MFA requires email verification. This prevents malicious actors from registering for a service with an email they don't own, and then locking out the real owner by adding a second factor.

  3. Register your app's SHA-1 hash in the Firebase Console (your changes will automatically carry over to Google Cloud Identity Platform).

    1. Follow the steps in Authenticating your client to obtain your app's SHA-1 hash.

    2. Open the Firebase Console .

    3. Navigate to Project Settings.

    4. Under Your apps, click the Android icon.

    5. Follow the guided steps to add your SHA-1 hash.

Enabling multi-factor authentication

  1. Go to the Identity Platform MFApage in the Google Cloud console.
    Go to MFA

  2. In Multi-Factor Authentication, click Enable.

  3. Enter the phone numbers you'll be testing your app with. While optional, registering test phone numbers is strongly recommended to avoid throttling during development.

  4. If you haven't already authorized your app's domain, add it to the allowlist by clicking Add domain.

  5. Click Save.

Choosing an enrollment pattern

You can choose whether your app requires multi-factor authentication, and how and when to enroll your users. Some common patterns include:

  • Enroll the user's second factor as part of registration. Use this method if your app requires multi-factor authentication for all users.

  • Offer a skippable option to enroll a second factor during registration. Apps that want to encourage, but not require, multi-factor authentication might prefer this approach.

  • Provide the ability to add a second factor from the user's account or profile management page, instead of the sign up screen. This minimizes friction during the registration process, while still making multi-factor authentication available for security-sensitive users.

  • Require adding a second factor incrementally when the user wants to access features with increased security requirements.

Enrolling a second factor

To enroll a new secondary factor for a user:

  1. Re-authenticate the user.

  2. Ask the user enter their phone number.

  3. Get a multi-factor session for the user:

    Kotlin+KTX

      user 
     . 
     multiFactor 
     . 
     session 
     . 
     addOnCompleteListener 
      
     { 
      
     task 
      
     - 
    >  
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ) 
      
     { 
      
     val 
      
     multiFactorSession 
     : 
      
     MultiFactorSession? 
     = 
      
     task 
     . 
     result 
      
     } 
     } 
     
    

    Java

      user 
     . 
     getMultiFactor 
     (). 
     getSession 
     () 
      
     . 
     addOnCompleteListener 
     ( 
      
     new 
      
     OnCompleteListener<MultiFactorSession> 
     () 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onComplete 
     ( 
     @NonNull 
      
     Task<MultiFactorSession> 
      
     task 
     ) 
      
     { 
      
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ()) 
      
     { 
      
     MultiFactorSession 
      
     multiFactorSession 
      
     = 
      
     task 
     . 
     getResult 
     (); 
      
     } 
      
     } 
      
     }); 
     
    
  4. Build an OnVerificationStateChangedCallbacks object to handle different events in the verification process:

    Kotlin+KTX

      val 
      
     callbacks 
      
     = 
      
     object 
      
     : 
      
     OnVerificationStateChangedCallbacks 
     () 
      
     { 
      
     override 
      
     fun 
      
     onVerificationCompleted 
     ( 
     credential 
     : 
      
     PhoneAuthCredential 
     ) 
      
     { 
      
     // This callback will be invoked in two situations: 
      
     // 1) Instant verification. In some cases, the phone number can be 
      
     //    instantly verified without needing to send or enter a verification 
      
     //    code. You can disable this feature by calling 
      
     //    PhoneAuthOptions.builder#requireSmsValidation(true) when building 
      
     //    the options to pass to PhoneAuthProvider#verifyPhoneNumber(). 
      
     // 2) Auto-retrieval. On some devices, Google Play services can 
      
     //    automatically detect the incoming verification SMS and perform 
      
     //    verification without user action. 
      
     this 
     @MainActivity.credential 
      
     = 
      
     credential 
      
     } 
      
     override 
      
     fun 
      
     onVerificationFailed 
     ( 
     e 
     : 
      
     FirebaseException 
     ) 
      
     { 
      
     // This callback is invoked in response to invalid requests for 
      
     // verification, like an incorrect phone number. 
      
     if 
      
     ( 
     e 
      
     is 
      
     FirebaseAuthInvalidCredentialsException 
     ) 
      
     { 
      
     // Invalid request 
      
     // ... 
      
     } 
      
     else 
      
     if 
      
     ( 
     e 
      
     is 
      
     FirebaseTooManyRequestsException 
     ) 
      
     { 
      
     // The SMS quota for the project has been exceeded 
      
     // ... 
      
     } 
      
     // Show a message and update the UI 
      
     // ... 
      
     } 
      
     override 
      
     fun 
      
     onCodeSent 
     ( 
      
     verificationId 
     : 
      
     String 
     , 
      
     forceResendingToken 
     : 
      
     ForceResendingToken 
      
     ) 
      
     { 
      
     // The SMS verification code has been sent to the provided phone number. 
      
     // We now need to ask the user to enter the code and then construct a 
      
     // credential by combining the code with a verification ID. 
      
     // Save the verification ID and resending token for later use. 
      
     this 
     @MainActivity.verificationId 
      
     = 
      
     verificationId 
      
     this 
     @MainActivity.forceResendingToken 
      
     = 
      
     forceResendingToken 
      
     // ... 
      
     } 
     } 
     
    

    Java

      OnVerificationStateChangedCallbacks 
      
     callbacks 
      
     = 
     new 
      
     OnVerificationStateChangedCallbacks 
     () 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onVerificationCompleted 
     ( 
     PhoneAuthCredential 
      
     credential 
     ) 
      
     { 
      
     // This callback will be invoked in two situations: 
      
     // 1) Instant verification. In some cases, the phone number can be 
      
     //    instantly verified without needing to send or enter a verification 
      
     //    code. You can disable this feature by calling 
      
     //    PhoneAuthOptions.builder#requireSmsValidation(true) when building 
      
     //    the options to pass to PhoneAuthProvider#verifyPhoneNumber(). 
      
     // 2) Auto-retrieval. On some devices, Google Play services can 
      
     //    automatically detect the incoming verification SMS and perform 
      
     //    verification without user action. 
      
     this 
     . 
     credential 
      
     = 
      
     credential 
     ; 
      
     } 
      
     @Override 
      
     public 
      
     void 
      
     onVerificationFailed 
     ( 
     FirebaseException 
      
     e 
     ) 
      
     { 
      
     // This callback is invoked in response to invalid requests for 
      
     // verification, like an incorrect phone number. 
      
     if 
      
     ( 
     e 
      
     instanceof 
      
     FirebaseAuthInvalidCredentialsException 
     ) 
      
     { 
      
     // Invalid request 
      
     // ... 
      
     } 
      
     else 
      
     if 
      
     ( 
     e 
      
     instanceof 
      
     FirebaseTooManyRequestsException 
     ) 
      
     { 
      
     // The SMS quota for the project has been exceeded 
      
     // ... 
      
     } 
      
     // Show a message and update the UI 
      
     // ... 
      
     } 
      
     @Override 
      
     public 
      
     void 
      
     onCodeSent 
     ( 
      
     String 
      
     verificationId 
     , 
      
     PhoneAuthProvider 
     . 
     ForceResendingToken 
      
     token 
     ) 
      
     { 
      
     // The SMS verification code has been sent to the provided phone number. 
      
     // We now need to ask the user to enter the code and then construct a 
      
     // credential by combining the code with a verification ID. 
      
     // Save the verification ID and resending token for later use. 
      
     this 
     . 
     verificationId 
      
     = 
      
     verificationId 
     ; 
      
     this 
     . 
     forceResendingToken 
      
     = 
      
     token 
     ; 
      
     // ... 
      
     } 
     }; 
     
    
  5. Initialize a PhoneInfoOptions object with the user's phone number, the multi-factor session, and your callbacks:

    Kotlin+KTX

      val 
      
     phoneAuthOptions 
      
     = 
      
     PhoneAuthOptions 
     . 
     newBuilder 
     () 
      
     . 
     setPhoneNumber 
     ( 
     phoneNumber 
     ) 
      
     . 
     setTimeout 
     ( 
     30L 
     , 
      
     TimeUnit 
     . 
     SECONDS 
     ) 
      
     . 
     setMultiFactorSession 
     ( 
     MultiFactorSession 
     ) 
      
     . 
     setCallbacks 
     ( 
     callbacks 
     ) 
      
     . 
     build 
     () 
     
    

    Java

      PhoneAuthOptions 
      
     phoneAuthOptions 
      
     = 
      
     PhoneAuthOptions 
     . 
     newBuilder 
     () 
      
     . 
     setPhoneNumber 
     ( 
     phoneNumber 
     ) 
      
     . 
     setTimeout 
     ( 
     30L 
     , 
      
     TimeUnit 
     . 
     SECONDS 
     ) 
      
     . 
     setMultiFactorSession 
     ( 
     multiFactorSession 
     ) 
      
     . 
     setCallbacks 
     ( 
     callbacks 
     ) 
      
     . 
     build 
     (); 
     
    

    By default, instant verification is enabled. To disable it, add a call to requireSmsValidation(true) .

  6. Send a verification message to the user's phone:

    Kotlin+KTX

      PhoneAuthProvider 
     . 
     verifyPhoneNumber 
     ( 
     phoneAuthOptions 
     ) 
     
    

    Java

      PhoneAuthProvider 
     . 
     verifyPhoneNumber 
     ( 
     phoneAuthOptions 
     ); 
     
    

    While not required, it's a best practice to inform users beforehand that they will receive an SMS message, and that standard rates apply.

  7. Once the SMS code is sent, ask the user to verify the code:

    Kotlin+KTX

      // Ask user for the verification code. 
     val 
      
     credential 
      
     = 
      
     PhoneAuthProvider 
     . 
     getCredential 
     ( 
     verificationId 
     , 
      
     verificationCode 
     ) 
     
    

    Java

      // Ask user for the verification code. 
     PhoneAuthCredential 
      
     credential 
      
     = 
      
     PhoneAuthProvider 
     . 
     getCredential 
     ( 
     verificationId 
     , 
      
     verificationCode 
     ); 
     
    
  8. Initialize a MultiFactorAssertion object with the PhoneAuthCredential :

    Kotlin+KTX

      val 
      
     multiFactorAssertion 
      
     = 
      
     PhoneMultiFactorGenerator 
     . 
     getAssertion 
     ( 
     credential 
     ) 
     
    

    Java

      MultiFactorAssertion 
      
     multiFactorAssertion 
      
     = 
      
     PhoneMultiFactorGenerator 
     . 
     getAssertion 
     ( 
     credential 
     ); 
     
    
  9. Complete the enrollment. Optionally, you can specify a display name for the second factor. This is useful for users with multiple second factors, since the phone number is masked during the authentication flow (for example, +1******1234).

    Kotlin+KTX

      // Complete enrollment. This will update the underlying tokens 
     // and trigger ID token change listener. 
     FirebaseAuth 
     . 
     getInstance 
     () 
      
     . 
     currentUser 
      
     ?. 
     multiFactor 
      
     ?. 
     enroll 
     ( 
     multiFactorAssertion 
     , 
      
     "My personal phone number" 
     ) 
      
     ?. 
     addOnCompleteListener 
      
     { 
      
     // ... 
      
     } 
     
    

    Java

      // Complete enrollment. This will update the underlying tokens 
     // and trigger ID token change listener. 
     FirebaseAuth 
     . 
     getInstance 
     () 
      
     . 
     getCurrentUser 
     () 
      
     . 
     getMultiFactor 
     () 
      
     . 
     enroll 
     ( 
     multiFactorAssertion 
     , 
      
     "My personal phone number" 
     ) 
      
     . 
     addOnCompleteListener 
     ( 
      
     new 
      
     OnCompleteListener<Void> 
     () 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onComplete 
     ( 
     @NonNull 
      
     Task<Void> 
      
     task 
     ) 
      
     { 
      
     // ... 
      
     } 
      
     }); 
     
    

The code below shows a complete example of enrolling a second factor:

Kotlin+KTX

  val 
  
 multiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ) 
 user 
 . 
 multiFactor 
 . 
 session 
  
 . 
 addOnCompleteListener 
  
 { 
  
 task 
  
 - 
>  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ) 
  
 { 
  
 val 
  
 multiFactorSession 
  
 = 
  
 task 
 . 
 result 
  
 val 
  
 phoneAuthOptions 
  
 = 
  
 PhoneAuthOptions 
 . 
 newBuilder 
 () 
  
 . 
 setPhoneNumber 
 ( 
 phoneNumber 
 ) 
  
 . 
 setTimeout 
 ( 
 30L 
 , 
  
 TimeUnit 
 . 
 SECONDS 
 ) 
  
 . 
 setMultiFactorSession 
 ( 
 multiFactorSession 
 ) 
  
 . 
 setCallbacks 
 ( 
 callbacks 
 ) 
  
 . 
 build 
 () 
  
 // Send SMS verification code. 
  
 PhoneAuthProvider 
 . 
 verifyPhoneNumber 
 ( 
 phoneAuthOptions 
 ) 
  
 } 
  
 } 
 // Ask user for the verification code. 
 val 
  
 credential 
  
 = 
  
 PhoneAuthProvider 
 . 
 getCredential 
 ( 
 verificationId 
 , 
  
 verificationCode 
 ) 
 val 
  
 multiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ) 
 // Complete enrollment. 
 FirebaseAuth 
 . 
 getInstance 
 () 
  
 . 
 currentUser 
  
 ?. 
 multiFactor 
  
 ?. 
 enroll 
 ( 
 multiFactorAssertion 
 , 
  
 "My personal phone number" 
 ) 
  
 ?. 
 addOnCompleteListener 
  
 { 
  
 // ... 
  
 } 
 

Java

  MultiFactorAssertion 
  
 multiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ); 
 user 
 . 
 getMultiFactor 
 (). 
 getSession 
 () 
  
 . 
 addOnCompleteListener 
 ( 
  
 new 
  
 OnCompleteListener<MultiFactorSession> 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
 @NonNull 
  
 Task<MultiFactorSession> 
  
 task 
 ) 
  
 { 
  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ()) 
  
 { 
  
 MultiFactorSession 
  
 multiFactorSession 
  
 = 
  
 task 
 . 
 getResult 
 (); 
  
 PhoneAuthOptions 
  
 phoneAuthOptions 
  
 = 
  
 PhoneAuthOptions 
 . 
 newBuilder 
 () 
  
 . 
 setPhoneNumber 
 ( 
 phoneNumber 
 ) 
  
 . 
 setTimeout 
 ( 
 30L 
 , 
  
 TimeUnit 
 . 
 SECONDS 
 ) 
  
 . 
 setMultiFactorSession 
 ( 
 multiFactorSession 
 ) 
  
 . 
 setCallbacks 
 ( 
 callbacks 
 ) 
  
 . 
 build 
 (); 
  
 // Send SMS verification code. 
  
 PhoneAuthProvider 
 . 
 verifyPhoneNumber 
 ( 
 phoneAuthOptions 
 ); 
  
 } 
  
 } 
  
 }); 
 // Ask user for the verification code. 
 PhoneAuthCredential 
  
 credential 
  
 = 
  
 PhoneAuthProvider 
 . 
 getCredential 
 ( 
 verificationId 
 , 
  
 verificationCode 
 ); 
 MultiFactorAssertion 
  
 multiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ); 
 // Complete enrollment. 
 FirebaseAuth 
 . 
 getInstance 
 () 
  
 . 
 getCurrentUser 
 () 
  
 . 
 getMultiFactor 
 () 
  
 . 
 enroll 
 ( 
 multiFactorAssertion 
 , 
  
 "My personal phone number" 
 ) 
  
 . 
 addOnCompleteListener 
 ( 
  
 new 
  
 OnCompleteListener<Void> 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
 @NonNull 
  
 Task<Void> 
  
 task 
 ) 
  
 { 
  
 // ... 
  
 } 
  
 }); 
 

Congratulations! You successfully registered a second authentication factor for a user.

Signing users in with a second factor

To sign in a user with two-factor SMS verification:

  1. Sign the user in with their first factor, then catch the FirebaseAuthMultiFactorException exception. This error contains a resolver, which you can use to obtain the user's enrolled second factors. It also contains an underlying session proving the user successfully authenticated with their first factor.

    For example, if the user's first factor was an email and password:

    Kotlin+KTX

      FirebaseAuth 
     . 
     getInstance 
     () 
      
     . 
     signInWithEmailAndPassword 
     ( 
     email 
     , 
      
     password 
     ) 
      
     . 
     addOnCompleteListener 
     ( 
      
     OnCompleteListener 
      
     { 
      
     task 
      
     - 
    >  
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ) 
      
     { 
      
     // User is not enrolled with a second factor and is successfully 
      
     // signed in. 
      
     // ... 
      
     return 
     @OnCompleteListener 
      
     } 
      
     if 
      
     ( 
     task 
     . 
     exception 
      
     is 
      
     FirebaseAuthMultiFactorException 
     ) 
      
     { 
      
     // The user is a multi-factor user. Second factor challenge is 
      
     // required. 
      
     val 
      
     multiFactorResolver 
      
     = 
      
     ( 
     task 
     . 
     exception 
      
     as 
      
     FirebaseAuthMultiFactorException 
     ). 
     resolver 
      
     // ... 
      
     } 
      
     else 
      
     { 
      
     // Handle other errors, such as wrong password. 
      
     } 
      
     }) 
     
    

    Java

      FirebaseAuth 
     . 
     getInstance 
     () 
      
     . 
     signInWithEmailAndPassword 
     ( 
     email 
     , 
      
     password 
     ) 
      
     . 
     addOnCompleteListener 
     ( 
      
     new 
      
     OnCompleteListener<AuthResult> 
     () 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onComplete 
     ( 
     @NonNull 
      
     Task<AuthResult> 
      
     task 
     ) 
      
     { 
      
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ()) 
      
     { 
      
     // User is not enrolled with a second factor and is successfully 
      
     // signed in. 
      
     // ... 
      
     return 
     ; 
      
     } 
      
     if 
      
     ( 
     task 
     . 
     getException 
     () 
      
     instanceof 
      
     FirebaseAuthMultiFactorException 
     ) 
      
     { 
      
     // The user is a multi-factor user. Second factor challenge is 
      
     // required. 
      
     MultiFactorResolver 
      
     multiFactorResolver 
      
     = 
      
     task 
     . 
     getException 
     (). 
     getResolver 
     (); 
      
     // ... 
      
     } 
      
     else 
      
     { 
      
     // Handle other errors such as wrong password. 
      
     } 
      
     } 
      
     }); 
     
    

    If the user's first factor is a federated provider, such as OAuth, catch the error after calling startActivityForSignInWithProvider() .

  2. If the user has multiple secondary factors enrolled, ask them which one to use:

    Kotlin+KTX

      // Ask user which second factor to use. 
     // You can get the list of enrolled second factors using 
     //   multiFactorResolver.hints 
     // Check the selected factor: 
     if 
      
     ( 
     multiFactorResolver 
     . 
     hints 
     [ 
     selectedIndex 
     ] 
     . 
     factorId 
      
     === 
      
     PhoneMultiFactorGenerator 
     . 
     FACTOR_ID 
     ) 
      
     { 
      
     // User selected a phone second factor. 
      
     val 
      
     selectedHint 
      
     = 
      
     multiFactorResolver 
     . 
     hints 
     [ 
     selectedIndex 
     ] 
      
     as 
      
     PhoneMultiFactorInfo 
     } 
      
     else 
      
     if 
      
     ( 
     multiFactorResolver 
     . 
     hints 
     [ 
     selectedIndex 
     ] 
     . 
     factorId 
      
     === 
      
     TotpMultiFactorGenerator 
     . 
     FACTOR_ID 
     ) 
      
     { 
      
     // User selected a TOTP second factor. 
     } 
      
     else 
      
     { 
      
     // Unsupported second factor. 
     } 
     
    

    Java

      // Ask user which second factor to use. 
     // You can get the masked phone number using 
     // resolver.getHints().get(selectedIndex).getPhoneNumber() 
     // You can get the display name using 
     // resolver.getHints().get(selectedIndex).getDisplayName() 
     if 
      
     ( 
      
     resolver 
     . 
     getHints 
     () 
      
     . 
     get 
     ( 
     selectedIndex 
     ) 
      
     . 
     getFactorId 
     () 
      
     . 
     equals 
     ( 
      
     PhoneMultiFactorGenerator 
     . 
     FACTOR_ID 
      
     ) 
      
     ) 
      
     { 
     // User selected a phone second factor. 
     MultiFactorInfo 
      
     selectedHint 
      
     = 
      
     multiFactorResolver 
     . 
     getHints 
     (). 
     get 
     ( 
     selectedIndex 
     ); 
     } 
      
     else 
      
     if 
      
     ( 
      
     resolver 
      
     . 
     getHints 
     () 
      
     . 
     get 
     ( 
     selectedIndex 
     ) 
      
     . 
     getFactorId 
     () 
      
     . 
     equals 
     ( 
     TotpMultiFactorGenerator 
     . 
     FACTOR_ID 
      
     ) 
      
     ) 
      
     { 
      
     // User selected a TOTP second factor. 
     } 
      
     else 
      
     { 
     // Unsupported second factor. 
     } 
     
    
  3. Initialize a PhoneAuthOptions object with the hint and multi-factor session. These values are contained in the resolver attached to the FirebaseAuthMultiFactorException .

    Kotlin+KTX

      val 
      
     phoneAuthOptions 
      
     = 
      
     PhoneAuthOptions 
     . 
     newBuilder 
     () 
      
     . 
     setMultiFactorHint 
     ( 
     selectedHint 
     ) 
      
     . 
     setTimeout 
     ( 
     30L 
     , 
      
     TimeUnit 
     . 
     SECONDS 
     ) 
      
     . 
     setMultiFactorSession 
     ( 
     multiFactorResolver 
     . 
     session 
     ) 
      
     . 
     setCallbacks 
     ( 
     callbacks 
     ) 
      
     // Optionally disable instant verification. 
      
     // .requireSmsValidation(true) 
      
     . 
     build 
     () 
     
    

    Java

      PhoneAuthOptions 
      
     phoneAuthOptions 
      
     = 
      
     PhoneAuthOptions 
     . 
     newBuilder 
     () 
      
     . 
     setMultiFactorHint 
     ( 
     selectedHint 
     ) 
      
     . 
     setTimeout 
     ( 
     30L 
     , 
      
     TimeUnit 
     . 
     SECONDS 
     ) 
      
     . 
     setMultiFactorSession 
     ( 
     multiFactorResolver 
     . 
     getSession 
     ()) 
      
     . 
     setCallbacks 
     ( 
     callbacks 
     ) 
      
     // Optionally disable instant verification. 
      
     // .requireSmsValidation(true) 
      
     . 
     build 
     (); 
     
    
  4. Send a verification message to the user's phone:

    Kotlin+KTX

      // Send SMS verification code 
     PhoneAuthProvider 
     . 
     verifyPhoneNumber 
     ( 
     phoneAuthOptions 
     ) 
     
    

    Java

      // Send SMS verification code 
     PhoneAuthProvider 
     . 
     verifyPhoneNumber 
     ( 
     phoneAuthOptions 
     ); 
     
    
  5. Once the SMS code is sent, ask the user to verify the code:

    Kotlin+KTX

      // Ask user for the verification code. Then, pass it to getCredential: 
     val 
      
     credential 
      
     = 
      
     PhoneAuthProvider 
     . 
     getCredential 
     ( 
     verificationId 
     , 
      
     verificationCode 
     ) 
     
    

    Java

      // Ask user for the verification code. Then, pass it to getCredential: 
     PhoneAuthCredential 
      
     credential 
      
     = 
      
     PhoneAuthProvider 
     . 
     getCredential 
     ( 
     verificationId 
     , 
      
     verificationCode 
     ); 
     
    
  6. Initialize a MultiFactorAssertion object with the PhoneAuthCredential :

    Kotlin+KTX

      val 
      
     multiFactorAssertion 
      
     = 
      
     PhoneMultiFactorGenerator 
     . 
     getAssertion 
     ( 
     credential 
     ) 
     
    

    Java

      MultiFactorAssertion 
      
     multiFactorAssertion 
      
     = 
      
     PhoneMultiFactorGenerator 
     . 
     getAssertion 
     ( 
     credential 
     ); 
     
    
  7. Call resolver.resolveSignIn() to complete secondary authentication. You can then access the original sign-in result, which includes the standard provider-specific data and authentication credentials:

    Kotlin+KTX

      multiFactorResolver 
      
     . 
     resolveSignIn 
     ( 
     multiFactorAssertion 
     ) 
      
     . 
     addOnCompleteListener 
      
     { 
      
     task 
      
     - 
    >  
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ) 
      
     { 
      
     val 
      
     authResult 
      
     = 
      
     task 
     . 
     result 
      
     // AuthResult will also contain the user, additionalUserInfo, 
      
     // and an optional credential (null for email/password) 
      
     // associated with the first factor sign-in. 
      
     // For example, if the user signed in with Google as a first 
      
     // factor, authResult.getAdditionalUserInfo() will contain data 
      
     // related to Google provider that the user signed in with; 
      
     // authResult.getCredential() will contain the Google OAuth 
      
     //   credential; 
      
     // authResult.getCredential().getAccessToken() will contain the 
      
     //   Google OAuth access token; 
      
     // authResult.getCredential().getIdToken() contains the Google 
      
     //   OAuth ID token. 
      
     } 
      
     } 
     
    

    Java

      multiFactorResolver 
      
     . 
     resolveSignIn 
     ( 
     multiFactorAssertion 
     ) 
      
     . 
     addOnCompleteListener 
     ( 
      
     new 
      
     OnCompleteListener<AuthResult> 
     () 
      
     { 
      
     @Override 
      
     public 
      
     void 
      
     onComplete 
     ( 
     @NonNull 
      
     Task<AuthResult> 
      
     task 
     ) 
      
     { 
      
     if 
      
     ( 
     task 
     . 
     isSuccessful 
     ()) 
      
     { 
      
     AuthResult 
      
     authResult 
      
     = 
      
     task 
     . 
     getResult 
     (); 
      
     // AuthResult will also contain the user, additionalUserInfo, 
      
     // and an optional credential (null for email/password) 
      
     // associated with the first factor sign-in. 
      
     // For example, if the user signed in with Google as a first 
      
     // factor, authResult.getAdditionalUserInfo() will contain data 
      
     // related to Google provider that the user signed in with. 
      
     // authResult.getCredential() will contain the Google OAuth 
      
     // credential. 
      
     // authResult.getCredential().getAccessToken() will contain the 
      
     // Google OAuth access token. 
      
     // authResult.getCredential().getIdToken() contains the Google 
      
     // OAuth ID token. 
      
     } 
      
     } 
      
     }); 
     
    

The code below shows a complete example of signing in a multi-factor user:

Kotlin+KTX

  FirebaseAuth 
 . 
 getInstance 
 () 
  
 . 
 signInWithEmailAndPassword 
 ( 
 email 
 , 
  
 password 
 ) 
  
 . 
 addOnCompleteListener 
  
 { 
  
 task 
  
 - 
>  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ) 
  
 { 
  
 // User is not enrolled with a second factor and is successfully 
  
 // signed in. 
  
 // ... 
  
 return 
 @addOnCompleteListener 
  
 } 
  
 if 
  
 ( 
 task 
 . 
 exception 
  
 is 
  
 FirebaseAuthMultiFactorException 
 ) 
  
 { 
  
 val 
  
 multiFactorResolver 
  
 = 
  
 ( 
 task 
 . 
 exception 
  
 as 
  
 FirebaseAuthMultiFactorException 
 ). 
 resolver 
  
 // Ask user which second factor to use. Then, get 
  
 // the selected hint: 
  
 val 
  
 selectedHint 
  
 = 
  
 multiFactorResolver 
 . 
 hints 
 [ 
 selectedIndex 
 ] 
  
 as 
  
 PhoneMultiFactorInfo 
  
 // Send the SMS verification code. 
  
 PhoneAuthProvider 
 . 
 verifyPhoneNumber 
 ( 
  
 PhoneAuthOptions 
 . 
 newBuilder 
 () 
  
 . 
 setActivity 
 ( 
 this 
 ) 
  
 . 
 setMultiFactorSession 
 ( 
 multiFactorResolver 
 . 
 session 
 ) 
  
 . 
 setMultiFactorHint 
 ( 
 selectedHint 
 ) 
  
 . 
 setCallbacks 
 ( 
 generateCallbacks 
 ()) 
  
 . 
 setTimeout 
 ( 
 30L 
 , 
  
 TimeUnit 
 . 
 SECONDS 
 ) 
  
 . 
 build 
 () 
  
 ) 
  
 // Ask user for the SMS verification code, then use it to get 
  
 // a PhoneAuthCredential: 
  
 val 
  
 credential 
  
 = 
  
 PhoneAuthProvider 
 . 
 getCredential 
 ( 
 verificationId 
 , 
  
 verificationCode 
 ) 
  
 // Initialize a MultiFactorAssertion object with the 
  
 // PhoneAuthCredential. 
  
 val 
  
 multiFactorAssertion 
 : 
  
 MultiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ) 
  
 // Complete sign-in. 
  
 multiFactorResolver 
  
 . 
 resolveSignIn 
 ( 
 multiFactorAssertion 
 ) 
  
 . 
 addOnCompleteListener 
  
 { 
  
 task 
  
 - 
>  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ) 
  
 { 
  
 // User successfully signed in with the 
  
 // second factor phone number. 
  
 } 
  
 // ... 
  
 } 
  
 } 
  
 else 
  
 { 
  
 // Handle other errors such as wrong password. 
  
 } 
  
 } 
 

Java

  FirebaseAuth 
 . 
 getInstance 
 () 
  
 . 
 signInWithEmailAndPassword 
 ( 
 email 
 , 
  
 password 
 ) 
  
 . 
 addOnCompleteListener 
 ( 
  
 new 
  
 OnCompleteListener<AuthResult> 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
 @NonNull 
  
 Task<AuthResult> 
  
 task 
 ) 
  
 { 
  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ()) 
  
 { 
  
 // User is not enrolled with a second factor and is successfully 
  
 // signed in. 
  
 // ... 
  
 return 
 ; 
  
 } 
  
 if 
  
 ( 
 task 
 . 
 getException 
 () 
  
 instanceof 
  
 FirebaseAuthMultiFactorException 
 ) 
  
 { 
  
 FirebaseAuthMultiFactorException 
  
 e 
  
 = 
  
 ( 
 FirebaseAuthMultiFactorException 
 ) 
  
 task 
 . 
 getException 
 (); 
  
 MultiFactorResolver 
  
 multiFactorResolver 
  
 = 
  
 e 
 . 
 getResolver 
 (); 
  
 // Ask user which second factor to use. 
  
 MultiFactorInfo 
  
 selectedHint 
  
 = 
  
 multiFactorResolver 
 . 
 getHints 
 (). 
 get 
 ( 
 selectedIndex 
 ); 
  
 // Send the SMS verification code. 
  
 PhoneAuthProvider 
 . 
 verifyPhoneNumber 
 ( 
  
 PhoneAuthOptions 
 . 
 newBuilder 
 () 
  
 . 
 setActivity 
 ( 
 this 
 ) 
  
 . 
 setMultiFactorSession 
 ( 
 multiFactorResolver 
 . 
 getSession 
 ()) 
  
 . 
 setMultiFactorHint 
 ( 
 selectedHint 
 ) 
  
 . 
 setCallbacks 
 ( 
 generateCallbacks 
 ()) 
  
 . 
 setTimeout 
 ( 
 30L 
 , 
  
 TimeUnit 
 . 
 SECONDS 
 ) 
  
 . 
 build 
 ()); 
  
 // Ask user for the SMS verification code. 
  
 PhoneAuthCredential 
  
 credential 
  
 = 
  
 PhoneAuthProvider 
 . 
 getCredential 
 ( 
 verificationId 
 , 
  
 verificationCode 
 ); 
  
 // Initialize a MultiFactorAssertion object with the 
  
 // PhoneAuthCredential. 
  
 MultiFactorAssertion 
  
 multiFactorAssertion 
  
 = 
  
 PhoneMultiFactorGenerator 
 . 
 getAssertion 
 ( 
 credential 
 ); 
  
 // Complete sign-in. 
  
 multiFactorResolver 
  
 . 
 resolveSignIn 
 ( 
 multiFactorAssertion 
 ) 
  
 . 
 addOnCompleteListener 
 ( 
  
 new 
  
 OnCompleteListener<AuthResult> 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
 @NonNull 
  
 Task<AuthResult> 
  
 task 
 ) 
  
 { 
  
 if 
  
 ( 
 task 
 . 
 isSuccessful 
 ()) 
  
 { 
  
 // User successfully signed in with the 
  
 // second factor phone number. 
  
 } 
  
 // ... 
  
 } 
  
 }); 
  
 } 
  
 else 
  
 { 
  
 // Handle other errors such as wrong password. 
  
 } 
  
 } 
  
 }); 
 

Congratulations! You successfully signed in a user using multi-factor authentication.

What's next

Design a Mobile Site
View Site in Mobile | Classic
Share by: