Multi-factor Auth
Increase security by adding Multi-factor authentication to your app.
Before a user can enroll a second factor they need to verify their email. See
User
interface is returned.
TOTP MFA
The official guide for Firebase web TOTP authentication explains the TOTP process well, including project prerequisites to enable the feature, as well as code examples.
The API details and usage examples may be combined with the full Phone auth example below to give you an MFA solution that fully supports TOTP or SMS MFA.
You may also find it useful to investigate the local / manual test screens that we use to verify this functionality.
Phone MFA
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
Begin by obtaining a MultiFactorUser
instance for the current user. This is the entry point for most multi-factor
operations:
import {
PhoneAuthProvider,
PhoneMultiFactorGenerator,
getAuth,
multiFactor,
} from '@react-native-firebase/auth';
const multiFactorUser = await multiFactor(getAuth().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 new PhoneAuthProvider(getAuth()).verifyPhoneNumber(phoneOptions);
Once the user has provided the verification code received by text message, you can complete the process:
const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = 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 phone 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 {
PhoneAuthProvider,
PhoneMultiFactorGenerator,
getAuth,
signInWithEmailAndPassword,
getMultiFactorResolver,
} from '@react-native-firebase/auth';
signInWithEmailAndPassword(getAuth(), 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 = getMultiFactorResolver(getAuth(), 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
}
if (resolver.hints[0].factorId === 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;
new PhoneAuthProvider(getAuth())
.verifyPhoneNumber(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 = PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = 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 {
PhoneAuthProvider,
PhoneMultiFactorGenerator,
getAuth,
signInWithEmailAndPassword,
getMultiFactorResolver,
} from '@react-native-firebase/auth';
signInWithEmailAndPassword(getAuth(), 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 = getMultiFactorResolver(error);
if (resolver.hints.length > 1) {
// Use resolver.hints to display a list of second factors to the user
}
if (resolver.hints[0].factorId === PhoneMultiFactorGenerator.FACTOR_ID) {
const hint = resolver.hints[0];
new PhoneAuthProvider(getAuth())
.verifyPhoneNumber({ multiFactorHint: hint, session: resolver.session }) // triggers the message to the user
.then(verificationId => setVerificationId(verificationId));
// Request verificationCode from user
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = 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.