Skip to main content

iOS Setup

Make sure to follow the official Identity Platform documentation to enable multi-factor authentication for your project and verify your app.

Enroll a new factor

Before a user can enroll a second factor they need to verify their email. See User interface is returned.

Begin by obtaining a MultiFactorUser instance for the current user. This is the entry point for most multi-factor operations:

import auth from '@react-native-firebase/auth';
const multiFactorUser = await auth().multiFactor(auth().currentUser);

Request the session identifier and use the phone number obtained from the user to send a verification code:

const session = await multiFactorUser.getSession();
const phoneOptions = {
phoneNumber,
session,
};

// Sends a text message to the user
const verificationId = await auth().verifyPhoneNumberForMultiFactor(phoneOptions);

Once the user has provided the verification code received by text message, you can complete the process:

const cred = auth.PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = auth.PhoneMultiFactorGenerator.assertion(cred);
await multiFactorUser.enroll(multiFactorAssertion, 'Optional display name for the user');

You can inspect User#multiFactor for information about the user's enrolled factors.

Sign-in flow using multi-factor

Ensure the account has already enrolled a second factor. Begin by calling the default sign-in methods, for example email and password. If the account requires a second factor to complete login, an exception will be raised:

import auth from '@react-native-firebase/auth';

auth()
.signInWithEmailAndPassword(email, password)
.then(() => {
// User has not enrolled a second factor
})
.catch(error => {
const { code } = error;
// Make sure to check if multi factor authentication is required
if (code === 'auth/multi-factor-auth-required') {
return;
}

// Other error
});

Using the error object you can obtain a MultiFactorResolver instance and continue the flow:

const resolver = auth().getMultiFactorResolver(error);

The resolver object has all the required information to prompt the user for a specific factor:

if (resolver.hints.length > 1) {
// Use resolver.hints to display a list of second factors to the user
}

// Currently only phone based factors are supported
if (resolver.hints[0].factorId === auth.PhoneMultiFactorGenerator.FACTOR_ID) {
// Continue with the sign-in flow
}

Using a multi-factor hint and the session information you can send a verification code to the user:

const hint = resolver.hints[0];
const sessionId = resolver.session;

auth()
.verifyPhoneNumberWithMultiFactorInfo(hint, sessionId) // triggers the message to the user
.then(verificationId => setVerificationId(verificationId));

Once the user has entered the verification code you can create a multi-factor assertion and finish the flow:

const credential = auth.PhoneAuthProvider.credential(verificationId, verificationCode);

const multiFactorAssertion = auth.PhoneMultiFactorGenerator.assertion(credential);

resolver.resolveSignIn(multiFactorAssertion).then(userCredential => {
// additionally onAuthStateChanged will be triggered as well
});

Upon successful sign-in, any onAuthStateChanged listeners will trigger with the new authentication state of the user.

To put the example together:

import auth from '@react-native-firebase/auth';

const authInstance = auth();

authInstance
.signInWithEmailAndPassword(email, password)
.then(() => {
// User has not enrolled a second factor
})
.catch(error => {
const { code } = error;
// Make sure to check if multi factor authentication is required
if (code === 'auth/multi-factor-auth-required') {
const resolver = auth.getMultiFactorResolver(error);

if (resolver.hints.length > 1) {
// Use resolver.hints to display a list of second factors to the user
}

// Currently only phone based factors are supported
if (resolver.hints[0].factorId === auth.PhoneMultiFactorGenerator.FACTOR_ID) {
const hint = resolver.hints[0];
const sessionId = resolver.session;

authInstance
.verifyPhoneNumberWithMultiFactorInfo(hint, sessionId) // triggers the message to the user
.then(verificationId => setVerificationId(verificationId));

// Request verificationCode from user

const credential = auth.PhoneAuthProvider.credential(verificationId, verificationCode);

const multiFactorAssertion = auth.PhoneMultiFactorGenerator.assertion(credential);

resolver.resolveSignIn(multiFactorAssertion).then(userCredential => {
// additionally onAuthStateChanged will be triggered as well
});
}
}
});

Testing

You can define test phone numbers and corresponding verification codes. The officialofficial guide contains more information on setting this up.