Если вы обновили Firebase Authentication до Identity Platform, вы можете добавить многофакторную аутентификацию по SMS в свое приложение Flutter.
Многофакторная аутентификация (МФА) повышает безопасность вашего приложения. Хотя злоумышленники часто взламывают пароли и учетные записи в социальных сетях, перехватить текстовое сообщение гораздо сложнее.
Прежде чем начать
Включите как минимум одного провайдера, поддерживающего многофакторную аутентификацию. Все провайдеры поддерживают многофакторную аутентификацию, за исключением аутентификации по телефону, анонимной аутентификации и Apple Game Center.
Убедитесь, что ваше приложение проверяет электронные адреса пользователей. Многофакторная аутентификация (MFA) требует подтверждения электронной почты. Это предотвращает регистрацию злоумышленниками в сервисе с использованием чужого адреса электронной почты, а затем блокировку доступа для настоящего владельца путем добавления второго фактора.
Android : Если вы еще не установили хеш SHA-256 для своего приложения в консоли Firebase , сделайте это. См. раздел «Аутентификация клиента» для получения информации о том, как найти хеш SHA-256 для вашего приложения.
iOS : В Xcode включите push-уведомления для вашего проекта и убедитесь, что ваш ключ аутентификации APNs настроен для 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.