Firebase Multi-Factor Authentication

How to Implement the Firebase Multi-Factor Authentication?

Hi 👋🏼, In the last article, we learned how to reset a password in the Firebase Auth System. In this Article, I will teach you how to implement the Multi-Factor Authentication (MFA). MFA will add a second level of security when your users sign-in to their accounts on your application, it consist on sending an SMS (text message) with a code to you user's phone that he needs to insert after signing in using email and password. MFA is not for every app as it's subjected to SIM swapping attacks, but having a second level of authentication is better than nothing. If your app stores sensitive information for example a bank website or cryptocurrency exchange don't implement SMS messaging, use the google authenticator app instead. We'll continue to work with the Firebase Emulator Suite and React with TypeScript.
Let's start!

Set Up reCAPTCHA and the Firebase file.

Before setting up the UI, we need to set the reCAPTCHA verifier; you have two options; one is to set the invisible reCAPTCHA passing the id of the button that will start the MFA, or use the visible reCAPTCHA and pass the container id in which reCAPTCHA will be launch. Also, the user email needs to be verified before enrolling in MFA.

  • Run the Firebase Emulator in the terminal with firebase emulators:start, add a user, and verify the email.

Firebase Emulator Auth

  • Start the enrollment with the startEnrollMultiFactor() function.
src/firebase/firebase.ts
  • Once the user obtains the verification code, finish the enrollment with finishEnrollMultiFactor() function.
src/firebase/firebase.ts

Create the MFA enrollment forms.

To implement MFA, we need to collect personal information from the user. Go to profile.tsx, and add a toggle button to launch the phone input with the user's country. According to Firebase, the phone number needs to be transformed into an E.164 format; to achieve this conversion, install the phone library. As an illustration, I'm passing the phone number as plain text; remember to add dashes for readability and inform the user that text message charges may apply.

src/routes/profile.tsx

Go to the routes folder and create the confirmMFaEnroll.tsx. This file will receive the code that Firebase sends to the user's cellphone; after the code has been accepted successfully, show a message or redirect the user back to his profile page.

src/routes/confirmMFaEnroll.tsx
  • Don't forget to import the new route inside the RequireAuth HOC.
src/App.tsx

How to Unenroll from the Firebase Multi-Factor Auth.

If your users want to unenroll from MFA, provide the MultiFactorUser.unenroll() function in the firebase.ts file. This function will unenroll all the user multi-factors.

src/firebase/firebase.ts
  • When the user turns off the toggle button, call the unEnrollMultiFactor() function.
src/routes/profile.tsx

If you want to maintain the state of the switch button, use the multiFactor() function. Check the state of the MFA enrollment every time the route profile is called; change the state of the switch button to true to avoid clearing the multi-factor on the initial render. You can create a spinner or a loading component to show it to the user while the app is checking if MFA is disabled.

src/components/loading/loading.tsx
src/routes/profile.tsx

Sign-in users with the Firebase MFA enabled.

If the user enrolls in MFA, he can no longer sign in regularly with email and password and the Firebase authentication system will throw an error auth/multi-factor-auth-required. We need to resolve the error to let the user enter the verification code he will receive on his cellphone.

First, add the getMultiFactorResolver(), the startMfaSignin(), and the finishMfaSignIn() functions to the firebase.ts

src/firebase/firebase.ts
  • Add the new error code to the Login form.
src/routes/home.tsx
  • Create a new HTML form where the user will insert the verification code and finish the sign-in process.
src/routes/signinMfa.tsx
  • Don't forget to add the new route to the App.tsx.
src/App.tsx