Если вы обновили Firebase Authentication with Identity Platform , вы можете добавить в свое приложение многофакторную аутентификацию (MFA) с использованием одноразовых паролей на основе времени (TOTP).
Firebase Authentication with Identity Platform позволяет использовать TOTP в качестве дополнительного фактора для многофакторной аутентификации (MFA). При включении этой функции пользователи, пытающиеся войти в ваше приложение, видят запрос на ввод TOTP. Для его генерации им необходимо использовать приложение-аутентификатор, способное генерировать действительные TOTP-коды, например, Google Authenticator .
Прежде чем начать
Включите хотя бы одного поставщика услуг, поддерживающего многофакторную аутентификацию (MFA). Обратите внимание, что все поставщики услуг, кроме следующих, поддерживают MFA:
- Авторизация по телефону
- Анонимная аутентификация
- Пользовательские токены аутентификации
- Apple Game Center
Убедитесь, что ваше приложение проверяет адреса электронной почты пользователей. Многофакторная аутентификация (MFA) требует подтверждения адреса электронной почты. Это предотвращает регистрацию злоумышленниками в сервисе с использованием адреса электронной почты, который им не принадлежит, и последующую блокировку доступа фактического владельца этого адреса путем добавления второго фактора.
Если вы еще этого не сделали, установите Firebase JavaScript SDK .
Многофакторная аутентификация TOTP поддерживается только в модульном веб-SDK, версиях v9.19.1 и выше.
Включить многофакторную аутентификацию TOTP
Чтобы включить TOTP в качестве второго фактора аутентификации, используйте Admin SDK или вызовите REST-конечную точку конфигурации проекта.
Для использования Admin SDK выполните следующие действия:
Если вы еще этого не сделали, установите Firebase Admin Node.js SDK .
Поддержка TOTP MFA доступна только в версиях 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 заключается в том, что когда две стороны (доказывающая и подтверждающая) генерируют OTP в течение одного и того же временного окна (обычно 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: Количество временных интервалов от нуля до десяти. Значение по умолчанию — пять.Принцип работы TOTP заключается в том, что когда две стороны (доказывающая и подтверждающая) генерируют OTP в течение одного и того же временного окна (обычно 30 секунд), они генерируют один и тот же пароль. Однако, чтобы учесть расхождение во времени между сторонами и время реакции человека, можно настроить службу TOTP таким образом, чтобы она принимала TOTP и из смежных временных окон.
Выберите схему зачисления
Вы можете выбрать, требуется ли вашему приложению многофакторная аутентификация, а также как и когда регистрировать пользователей. К распространенным сценариям относятся следующие:
Включите второй фактор аутентификации пользователя в процесс регистрации. Используйте этот метод, если ваше приложение требует многофакторной аутентификации для всех пользователей.
Предложите возможность пропустить регистрацию и добавить второй фактор аутентификации. Если вы хотите поощрять, но не требовать многофакторную аутентификацию в своем приложении, вы можете использовать этот подход.
Предоставьте возможность добавления второго фактора аутентификации на странице управления учетной записью или профилем пользователя, а не на экране регистрации. Это минимизирует сложности в процессе регистрации, сохраняя при этом возможность многофакторной аутентификации для пользователей, которым важна безопасность.
Необходимо постепенно вводить второй фактор аутентификации при каждом желании пользователя получить доступ к функциям с повышенными требованиями к безопасности.
Зарегистрируйте пользователей в системе многофакторной аутентификации TOTP.
После включения TOTP MFA в качестве второго фактора для вашего приложения, реализуйте логику на стороне клиента для регистрации пользователей в 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 используйте следующий код:
Импортируйте необходимые классы и функции многофакторной аутентификации (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; } }В процессе многофакторной аутентификации (MFA) вашего приложения пользователю сначала следует предложить выбрать второй фактор аутентификации. Список поддерживаемых вторых факторов можно получить, изучив свойство
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 MFA
В этом разделе описывается, как обрабатывать случаи отмены пользователем участия в многофакторной аутентификации 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 .