Если вы перешли на аутентификацию Firebase с Identity Platform, вы можете добавить многофакторную аутентификацию по SMS в свое приложение Flutter.
Многофакторная аутентификация (MFA) повышает безопасность вашего приложения. Хотя злоумышленники часто взламывают пароли и аккаунты социальных сетей, перехватить SMS-сообщение гораздо сложнее.
Прежде чем начать
Включите хотя бы одного поставщика, поддерживающего многофакторную аутентификацию. Все поставщики поддерживают MFA, за исключением аутентификации по телефону, анонимной аутентификации и Apple Game Center.
Убедитесь, что ваше приложение проверяет адреса электронной почты пользователей. Многофакторная аутентификация (MFA) требует подтверждения адреса электронной почты. Это предотвращает возможность злоумышленников регистрироваться в сервисе, используя адрес электронной почты, которому они не принадлежат, а затем блокировать доступ настоящего владельца, добавляя второй фактор аутентификации.
Android : Если вы ещё не установили хэш SHA-256 своего приложения в консоли Firebase , сделайте это. Сведения о поиске хэша SHA-256 приложения см. в разделе «Аутентификация клиента» .
iOS : В Xcode включите push-уведомления для своего проекта и убедитесь, что ключ аутентификации APN настроен на Firebase Cloud Messaging (FCM) . Кроме того, необходимо включить фоновые режимы для удалённых уведомлений. Подробное описание этого шага см. в документации Firebase iOS Phone Auth .
Веб : Убедитесь, что вы добавили домен своего приложения в консоль Firebase в разделе Домены перенаправления OAuth .
Включение многофакторной аутентификации
Откройте страницу Аутентификация > Метод входа в консоли Firebase.
В разделе «Дополнительно» включите SMS-многофакторную аутентификацию .
Вам также следует указать номера телефонов, на которых вы будете тестировать приложение. Регистрация тестовых номеров телефонов необязательна, но настоятельно рекомендуется, чтобы избежать ограничений во время разработки.
Если вы еще не авторизовали домен своего приложения, добавьте его в список разрешенных на странице Аутентификация > Настройки консоли Firebase.
Выбор схемы зачисления
Вы можете выбрать, требуется ли вашему приложению многофакторная аутентификация, а также как и когда регистрировать пользователей. Вот некоторые распространённые шаблоны:
Включите второй фактор аутентификации пользователя в процесс регистрации. Используйте этот метод, если ваше приложение требует многофакторной аутентификации для всех пользователей.
Предложите возможность пропуска второго фактора аутентификации при регистрации. Этот подход может быть предпочтителен для приложений, которые хотят поощрять, но не требовать многофакторную аутентификацию.
Предоставьте возможность добавления второго фактора на странице управления учётной записью или профилем пользователя, а не на экране регистрации. Это минимизирует сложности в процессе регистрации, сохраняя при этом доступность многофакторной аутентификации для пользователей, которым важны вопросы безопасности.
Требуйте постепенного добавления второго фактора, когда пользователь захочет получить доступ к функциям с повышенными требованиями к безопасности.
Регистрация второго фактора
Чтобы зарегистрировать новый вторичный фактор для пользователя:
Повторно аутентифицируйте пользователя.
Попросите пользователя ввести свой номер телефона.
Получите многофакторную сессию для пользователя:
final multiFactorSession = await user.multiFactor.getSession();Проверьте номер телефона с помощью многофакторного сеанса и ваших обратных звонков:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: multiFactorSession, phoneNumber: phoneNumber, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // The SMS verification code has been sent to the provided phone number. // ... }, codeAutoRetrievalTimeout: (_) {}, );После отправки SMS-кода попросите пользователя подтвердить код:
final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, );Завершите регистрацию:
await user.multiFactor.enroll( PhoneMultiFactorGenerator.getAssertion( credential, ), );
Приведенный ниже код демонстрирует полный пример регистрации второго фактора:
final session = await user.multiFactor.getSession();
final auth = FirebaseAuth.instance;
await auth.verifyPhoneNumber(
multiFactorSession: session,
phoneNumber: phoneController.text,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await user.multiFactor.enroll(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
Поздравляем! Вы успешно зарегистрировали второй фактор аутентификации для пользователя.
Вход пользователей с использованием второго фактора
Чтобы авторизовать пользователя с двухфакторной аутентификацией по SMS:
Авторизуйте пользователя с использованием его первого фактора, а затем перехватите исключение
FirebaseAuthMultiFactorException. Эта ошибка содержит резолвер, который можно использовать для получения зарегистрированных вторых факторов пользователя. Она также содержит базовый сеанс, подтверждающий успешную аутентификацию пользователя с использованием первого фактора.Например, если первым фактором пользователя был адрес электронной почты и пароль:
try { await _auth.signInWithEmailAndPassword( email: emailController.text, password: passwordController.text, ); // User is not enrolled with a second factor and is successfully // signed in. // ... } on FirebaseAuthMultiFactorException catch (e) { // The user is a multi-factor user. Second factor challenge is required final resolver = e.resolver // ... }Если у пользователя зарегистрировано несколько вторичных факторов, спросите его, какой из них использовать:
final session = e.resolver.session; final hint = e.resolver.hints[selectedHint];Отправьте на телефон пользователя проверочное сообщение с подсказкой и сеансом многофакторной аутентификации:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: session, multiFactorInfo: hint, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // ... }, codeAutoRetrievalTimeout: (_) {}, );Вызовите
resolver.resolveSignIn()для завершения вторичной аутентификации:final smsCode = await getSmsCodeFromUser(context); if (smsCode != null) { // Create a PhoneAuthCredential with the code final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, ); try { await e.resolver.resolveSignIn( PhoneMultiFactorGenerator.getAssertion(credential) ); } on FirebaseAuthException catch (e) { print(e.message); } }
В коде ниже показан полный пример входа пользователя с многофакторной аутентификацией:
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text,
password: passwordController.text,
);
} on FirebaseAuthMultiFactorException catch (e) {
setState(() {
error = '${e.message}';
});
final firstHint = e.resolver.hints.first;
if (firstHint is! PhoneMultiFactorInfo) {
return;
}
await FirebaseAuth.instance.verifyPhoneNumber(
multiFactorSession: e.resolver.session,
multiFactorInfo: firstHint,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await e.resolver.resolveSignIn(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
} catch (e) {
...
}
Поздравляем! Вы успешно авторизовали пользователя, используя многофакторную аутентификацию.
Что дальше?
- Управляйте многофакторными пользователями программно с помощью Admin SDK.