Если вы перешли на версию Firebase Authentication with Identity Platform, то можете добавить в приложение многофакторную аутентификацию (МФА) с использованием одноразовых кодов на основе времени (TOTP).
Firebase Authentication with Identity Platform позволяет использовать TOTP в качестве дополнительного фактора для многофакторной аутентификации. Когда вы включите эту функцию, пользователи, пытающиеся войти в ваше приложение, будут получать запрос на ввод одноразового пароля. Для этого нужно использовать приложение для аутентификации, которое может генерировать действительные коды TOTP, например Google Authenticator.
Подготовка
Включите хотя бы одного поставщика, поддерживающего многофакторную аутентификацию. Обратите внимание, что многофакторную аутентификацию поддерживают все поставщики, кроме перечисленных ниже:
- Аутентификация по номеру телефона
- Анонимная аутентификация
- Пользовательские токены аутентификации
- Apple Game Center
Убедитесь, что ваше приложение проверяет адреса электронной почты пользователей. Для многофакторной аутентификации требуется подтверждение адреса электронной почты. Это не позволит злоумышленникам зарегистрироваться в сервисе, используя чужой адрес электронной почты, а затем заблокировать доступ к нему, добавив второй фактор.
Если вы ещё не сделали этого, установите Firebase JavaScript SDK.
Многофакторная аутентификация с помощью TOTP поддерживается только в модульной версии Web SDK 9.19.1 и более поздних.
Как включить многофакторную аутентификацию на основе TOTP
Чтобы включить TOTP в качестве второго фактора, используйте Admin SDK или вызовите конечную точку REST для конфигурации проекта.
Чтобы использовать Admin SDK, выполните следующие действия:
Если вы ещё этого не сделали, установите Firebase Admin Node.js SDK.
Многофакторная аутентификация с помощью TOTP поддерживается только в Firebase Admin Node.js SDK версии 11.6.0 и выше.
Выполните следующие действия:
import { getAuth } from 'firebase-admin/auth'; getAuth().projectConfigManager().updateProjectConfig( { multiFactorConfig: { providerConfigs: [{ state: "ENABLED", totpProviderConfig: { adjacentIntervals: NUM_ADJ_INTERVALS } }] } })Замените следующее:
NUM_ADJ_INTERVALS: количество соседних временных интервалов, из которых можно принимать TOTP (от нуля до десяти). Значение по умолчанию – пять.TOTP-коды работают так, что, когда две стороны (доказывающая и проверяющая) генерируют одноразовые пароли в течение одного временного окна (обычно 30 секунд), они получают один и тот же пароль. Однако, чтобы учесть расхождение во времени между сторонами и время реакции человека, вы можете настроить сервис TOTP так, чтобы он принимал коды TOTP из соседних временных окон.
Чтобы включить многофакторную аутентификацию с помощью TOTP с использованием REST API, выполните следующие действия:
curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-H "X-Goog-User-Project: PROJECT_ID" \
-d \
'{
"mfa": {
"providerConfigs": [{
"state": "ENABLED",
"totpProviderConfig": {
"adjacentIntervals": NUM_ADJ_INTERVALS
}
}]
}
}'
Замените следующее:
PROJECT_ID– идентификатор проекта.NUM_ADJ_INTERVALS– количество временных интервалов (от 0 до 10). Значение по умолчанию – пять.TOTP-коды работают так, что, когда две стороны (доказывающая и проверяющая) генерируют одноразовые пароли в течение одного временного окна (обычно 30 секунд), они получают один и тот же пароль. Однако, чтобы учесть расхождение во времени между сторонами и время реакции человека, вы можете настроить сервис TOTP так, чтобы он принимал коды TOTP из соседних временных окон.
Как выбрать шаблон регистрации
Вы можете выбрать, требуется ли для вашего приложения многофакторная аутентификация, а также как и когда регистрировать пользователей. Вот некоторые распространенные паттерны:
Зарегистрируйте второй фактор аутентификации пользователя в рамках регистрации. Используйте этот метод, если для вашего приложения требуется многофакторная аутентификация для всех пользователей.
Предлагайте пользователям зарегистрировать второй фактор во время регистрации, но не делайте это обязательным. Если вы хотите рекомендовать, но не требовать многофакторную аутентификацию в приложении, можно использовать этот подход.
Предоставьте возможность добавить второй фактор на странице управления аккаунтом или профилем пользователя, а не на экране регистрации. Это упрощает процесс регистрации, но при этом позволяет пользователям, которым важна безопасность, включить многофакторную аутентификацию.
Постепенно добавлять второй фактор, когда пользователь хочет получить доступ к функциям с повышенными требованиями к безопасности.
Как зарегистрировать пользователей для многофакторной аутентификации с помощью TOTP
После того как вы включите многофакторную аутентификацию с использованием TOTP в качестве второго фактора для своего приложения, реализуйте на стороне клиента логику регистрации пользователей в TOTP MFA:
Импортируйте необходимые классы и функции MFA:
import { multiFactor, TotpMultiFactorGenerator, TotpSecret, getAuth, } from "firebase/auth";Повторно аутентифицируйте пользователя.
Сгенерируйте секретный код TOTP для аутентифицированного пользователя:
// Generate a TOTP secret. const multiFactorSession = await multiFactor(currentUser).getSession(); const totpSecret = await TotpMultiFactorGenerator.generateSecret( multiFactorSession );Покажите пользователю секретный ключ и предложите ввести его в приложении для аутентификации.
Во многих приложениях для аутентификации пользователи могут быстро добавлять новые секреты TOTP, сканируя QR-код, который представляет собой URI ключа, совместимый с Google Authenticator. Чтобы создать QR-код для этой цели, сгенерируйте URI с помощью
generateQrCodeUrl(), а затем закодируйте его с помощью библиотеки QR-кодов по вашему выбору. Пример:const totpUri = totpSecret.generateQrCodeUrl( currentUser.email, "Your App's Name" ); await QRExampleLib.toCanvas(totpUri, qrElement);Независимо от того, показываете ли вы QR-код, всегда показывайте секретный ключ, чтобы поддерживать приложения-аутентификаторы, которые не могут считывать QR-коды:
// Also display this key: const secret = totpSecret.secretKey;После того как пользователь добавит секретный ключ в приложение для аутентификации, оно начнет генерировать TOTP.
Попросите пользователя ввести TOTP, показанный в приложении для аутентификации, и использовать его для завершения регистрации многофакторной аутентификации:
// Ask the user for a verification code from the authenticator app. const verificationCode = // Code from user input. // Finalize the enrollment. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment( totpSecret, verificationCode ); await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
Как настроить вход с использованием второго фактора
Чтобы пользователи могли входить в аккаунт с помощью многофакторной аутентификации на основе TOTP, используйте следующий код:
Импортируйте необходимые классы и функции MFA:
import { getAuth, getMultiFactorResolver, TotpMultiFactorGenerator, } from "firebase/auth";Вызовите один из методов
signInWithтак же, как если бы вы не использовали многофакторную аутентификацию. (например,signInWithEmailAndPassword()). Если метод возвращает ошибкуauth/multi-factor-auth-required, запустите многофакторную аутентификацию в приложении.try { const userCredential = await signInWithEmailAndPassword( getAuth(), email, password ); // If the user is not enrolled with a second factor and provided valid // credentials, sign-in succeeds. // (If your app requires MFA, this could be considered an error // condition, which you would resolve by forcing the user to enroll a // second factor.) // ... } catch (error) { switch (error.code) { case "auth/multi-factor-auth-required": // Initiate your second factor sign-in flow. (See next step.) // ... break; case ...: // Handle other errors, such as wrong passwords. break; } }В процессе многофакторной аутентификации сначала предложите пользователю выбрать второй фактор. Список поддерживаемых вторых факторов можно получить, изучив свойство
hintsэкземпляраMultiFactorResolver:const mfaResolver = getMultiFactorResolver(getAuth(), error); const enrolledFactors = mfaResolver.hints.map(info => info.displayName);Если пользователь выберет TOTP, предложите ему ввести TOTP, который показывается в приложении для аутентификации, и использовать его для входа в аккаунт:
switch (mfaResolver.hints[selectedIndex].factorId) { case TotpMultiFactorGenerator.FACTOR_ID: const otpFromAuthenticator = // OTP typed by the user. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForSignIn( mfaResolver.hints[selectedIndex].uid, otpFromAuthenticator ); try { const userCredential = await mfaResolver.resolveSignIn( multiFactorAssertion ); // Successfully signed in! } catch (error) { // Invalid or expired OTP. } break; case PhoneMultiFactorGenerator.FACTOR_ID: // Handle SMS second factor. break; default: // Unsupported second factor? break; }
Как отменить регистрацию в многофакторной аутентификации с помощью TOTP
В этом разделе описано, как отменить регистрацию пользователя в многофакторной аутентификации с помощью TOTP.
Если пользователь зарегистрировал несколько способов многофакторной аутентификации и отменил регистрацию последнего из них, он получит сообщение auth/user-token-expired и будет выведен из системы. Пользователю нужно будет снова войти в аккаунт и подтвердить имеющиеся учетные данные, например адрес электронной почты и пароль.
Чтобы отменить регистрацию пользователя, обработать ошибку и запустить повторную аутентификацию, используйте следующий код:
import {
EmailAuthProvider,
TotpMultiFactorGenerator,
getAuth,
multiFactor,
reauthenticateWithCredential,
} from "firebase/auth";
try {
// Unenroll from TOTP MFA.
await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch (error) {
if (error.code === 'auth/user-token-expired') {
// If the user was signed out, re-authenticate them.
// For example, if they signed in with a password, prompt them to
// provide it again, then call `reauthenticateWithCredential()` as shown
// below.
const credential = EmailAuthProvider.credential(email, password);
await reauthenticateWithCredential(
currentUser,
credential
);
}
}
Дальнейшие действия
- Управлять пользователями с многофакторной аутентификацией программно с помощью Admin SDK.