Некоторые действия по управлению пользователями, например изменение адреса электронной почты или сброс пароля, приводят к отправке пользователю электронных писем. В этих письмах есть ссылки, по которым получатели могут перейти, чтобы завершить или отменить действие по управлению пользователем. По умолчанию в письмах об управлении пользователями есть ссылки на обработчик действий по умолчанию – веб-страницу, размещенную по URL в домене Firebase Hosting вашего проекта.
Вместо этого вы можете создать и разместить специальный обработчик действий с электронной почтой, чтобы выполнять собственные операции и интегрировать обработчик действий с электронной почтой с вашим сайтом.
Для выполнения следующих действий по управлению пользователями необходимо использовать обработчик действий электронной почты:
- Как сбросить пароль
- Отмена изменения адреса электронной почты – когда пользователи меняют основной адрес электронной почты в аккаунте, Firebase отправляет на старый адрес письмо, позволяющее отменить изменение.
- Как подтвердить адрес электронной почты
Чтобы настроить обработчик действий с электронной почтой в проекте Firebase, создайте и разместите веб-страницу, на которой с помощью Firebase JavaScript SDK проверяется действительность запроса и выполняется запрос. Затем вам нужно будет настроить шаблоны электронных писем в проекте Firebase, чтобы они ссылались на ваш обработчик пользовательских действий.
Как создать страницу обработчика действий с электронной почтой
Когда Firebase создает электронные письма для управления пользователями, в URL обработчика действий добавляются несколько параметров запроса. Пример:
https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr
Эти параметры указывают, какую задачу по управлению пользователями выполняет пользователь. Страница обработчика действий с электронной почтой должна обрабатывать следующие параметры запроса:
Параметры режим Действие по управлению пользователями, которое нужно выполнить. Может принимать одно из следующих значений:
resetPasswordrecoverEmailverifyEmail
oobCode Одноразовый код, используемый для идентификации и проверки запроса. apiKey Ключ API проекта Firebase (для удобства) continueUrl Это необязательный URL, который позволяет передавать данные обратно в приложение через URL. Это относится к режимам сброса пароля и подтверждения адреса электронной почты. При отправке письма для сброса пароля или письма с подтверждением необходимо указать объект ActionCodeSettingsс URL продолжения, чтобы эта функция была доступна. Это позволяет пользователю продолжить работу с того места, на котором он остановился после выполнения действия в письме.lang Необязательный тег языка BCP47 , представляющий локаль пользователя (например,
fr). Это значение можно использовать, чтобы показывать пользователям локализованные страницы обработчика действий с электронной почтой.Локализацию можно задать в консоли Firebase или динамически, вызвав соответствующий клиентский API перед запуском действия отправки электронного письма. Например, с помощью JavaScript:
firebase.auth().languageCode = 'fr';.Чтобы обеспечить единообразный пользовательский интерфейс, убедитесь, что локализация обработчика действий с электронной почтой соответствует локализации шаблона письма.
В примере ниже показано, как обрабатывать параметры запроса в обработчике на основе браузера. (Обработчик также можно реализовать как приложение Node.js, используя аналогичную логику.)
Web
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; document.addEventListener('DOMContentLoaded', () => { // TODO: Implement getParameterByName() // Get the action to complete. const mode = getParameterByName('mode'); // Get the one-time code from the query parameter. const actionCode = getParameterByName('oobCode'); // (Optional) Get the continue URL from the query parameter if available. const continueUrl = getParameterByName('continueUrl'); // (Optional) Get the language code if available. const lang = getParameterByName('lang') || 'en'; // Configure the Firebase SDK. // This is the minimum configuration required for the API to be used. const config = { 'apiKey': "YOUR_API_KEY" // Copy this key from the web initialization // snippet found in the Firebase console. }; const app = initializeApp(config); const auth = getAuth(app); // Handle the user management action. switch (mode) { case 'resetPassword': // Display reset password handler and UI. handleResetPassword(auth, actionCode, continueUrl, lang); break; case 'recoverEmail': // Display email recovery handler and UI. handleRecoverEmail(auth, actionCode, lang); break; case 'verifyEmail': // Display email verification handler and UI. handleVerifyEmail(auth, actionCode, continueUrl, lang); break; default: // Error: invalid mode. } }, false);
Web
document.addEventListener('DOMContentLoaded', () => { // TODO: Implement getParameterByName() // Get the action to complete. var mode = getParameterByName('mode'); // Get the one-time code from the query parameter. var actionCode = getParameterByName('oobCode'); // (Optional) Get the continue URL from the query parameter if available. var continueUrl = getParameterByName('continueUrl'); // (Optional) Get the language code if available. var lang = getParameterByName('lang') || 'en'; // Configure the Firebase SDK. // This is the minimum configuration required for the API to be used. var config = { 'apiKey': "YOU_API_KEY" // Copy this key from the web initialization // snippet found in the Firebase console. }; var app = firebase.initializeApp(config); var auth = app.auth(); // Handle the user management action. switch (mode) { case 'resetPassword': // Display reset password handler and UI. handleResetPassword(auth, actionCode, continueUrl, lang); break; case 'recoverEmail': // Display email recovery handler and UI. handleRecoverEmail(auth, actionCode, lang); break; case 'verifyEmail': // Display email verification handler and UI. handleVerifyEmail(auth, actionCode, continueUrl, lang); break; default: // Error: invalid mode. } }, false);
Обрабатывайте запросы на сброс пароля, сначала проверяя код действия с помощью
verifyPasswordResetCode, а затем получая новый пароль от пользователя и передавая его вconfirmPasswordReset. Пример:Web
import { verifyPasswordResetCode, confirmPasswordReset } from "firebase/auth"; function handleResetPassword(auth, actionCode, continueUrl, lang) { // Localize the UI to the selected language as determined by the lang // parameter. // Verify the password reset code is valid. verifyPasswordResetCode(auth, actionCode).then((email) => { const accountEmail = email; // TODO: Show the reset screen with the user's email and ask the user for // the new password. const newPassword = "..."; // Save the new password. confirmPasswordReset(auth, actionCode, newPassword).then((resp) => { // Password reset has been confirmed and new password updated. // TODO: Display a link back to the app, or sign-in the user directly // if the page belongs to the same domain as the app: // auth.signInWithEmailAndPassword(accountEmail, newPassword); // TODO: If a continue URL is available, display a button which on // click redirects the user back to the app via continueUrl with // additional state determined from that URL's parameters. }).catch((error) => { // Error occurred during confirmation. The code might have expired or the // password is too weak. }); }).catch((error) => { // Invalid or expired action code. Ask user to try to reset the password // again. }); }
Web
function handleResetPassword(auth, actionCode, continueUrl, lang) { // Localize the UI to the selected language as determined by the lang // parameter. // Verify the password reset code is valid. auth.verifyPasswordResetCode(actionCode).then((email) => { var accountEmail = email; // TODO: Show the reset screen with the user's email and ask the user for // the new password. var newPassword = "..."; // Save the new password. auth.confirmPasswordReset(actionCode, newPassword).then((resp) => { // Password reset has been confirmed and new password updated. // TODO: Display a link back to the app, or sign-in the user directly // if the page belongs to the same domain as the app: // auth.signInWithEmailAndPassword(accountEmail, newPassword); // TODO: If a continue URL is available, display a button which on // click redirects the user back to the app via continueUrl with // additional state determined from that URL's parameters. }).catch((error) => { // Error occurred during confirmation. The code might have expired or the // password is too weak. }); }).catch((error) => { // Invalid or expired action code. Ask user to try to reset the password // again. }); }
Чтобы отменить изменение адреса электронной почты, сначала проверьте код действия с помощью
checkActionCode, а затем восстановите адрес электронной почты пользователя с помощьюapplyActionCode. Пример:Web
import { checkActionCode, applyActionCode, sendPasswordResetEmail } from "firebase/auth"; function handleRecoverEmail(auth, actionCode, lang) { // Localize the UI to the selected language as determined by the lang // parameter. let restoredEmail = null; // Confirm the action code is valid. checkActionCode(auth, actionCode).then((info) => { // Get the restored email address. restoredEmail = info['data']['email']; // Revert to the old email. return applyActionCode(auth, actionCode); }).then(() => { // Account email reverted to restoredEmail // TODO: Display a confirmation message to the user. // You might also want to give the user the option to reset their password // in case the account was compromised: sendPasswordResetEmail(auth, restoredEmail).then(() => { // Password reset confirmation sent. Ask user to check their email. }).catch((error) => { // Error encountered while sending password reset code. }); }).catch((error) => { // Invalid code. }); }
Web
function handleRecoverEmail(auth, actionCode, lang) { // Localize the UI to the selected language as determined by the lang // parameter. var restoredEmail = null; // Confirm the action code is valid. auth.checkActionCode(actionCode).then((info) => { // Get the restored email address. restoredEmail = info['data']['email']; // Revert to the old email. return auth.applyActionCode(actionCode); }).then(() => { // Account email reverted to restoredEmail // TODO: Display a confirmation message to the user. // You might also want to give the user the option to reset their password // in case the account was compromised: auth.sendPasswordResetEmail(restoredEmail).then(() => { // Password reset confirmation sent. Ask user to check their email. }).catch((error) => { // Error encountered while sending password reset code. }); }).catch((error) => { // Invalid code. }); }
Обрабатывайте подтверждение адреса электронной почты, вызывая функцию
applyActionCode. Пример:Web
function handleVerifyEmail(auth, actionCode, continueUrl, lang) { // Localize the UI to the selected language as determined by the lang // parameter. // Try to apply the email verification code. applyActionCode(auth, actionCode).then((resp) => { // Email address has been verified. // TODO: Display a confirmation message to the user. // You could also provide the user with a link back to the app. // TODO: If a continue URL is available, display a button which on // click redirects the user back to the app via continueUrl with // additional state determined from that URL's parameters. }).catch((error) => { // Code is invalid or expired. Ask the user to verify their email address // again. }); }
Web
function handleVerifyEmail(auth, actionCode, continueUrl, lang) { // Localize the UI to the selected language as determined by the lang // parameter. // Try to apply the email verification code. auth.applyActionCode(actionCode).then((resp) => { // Email address has been verified. // TODO: Display a confirmation message to the user. // You could also provide the user with a link back to the app. // TODO: If a continue URL is available, display a button which on // click redirects the user back to the app via continueUrl with // additional state determined from that URL's parameters. }).catch((error) => { // Code is invalid or expired. Ask the user to verify their email address // again. }); }
Разместите страницу на хостинге, например Firebase Hosting.
Устранение неполадок: устаревший или недействительный ключ API в ссылках на действия
Серверная часть Firebase Authentication управляет ключом API, встроенным в сгенерированные ссылки на действия, например параметром apiKey в URL. Если вы смените ключи API проекта или удалите ключ, изначально связанный с аутентификацией Firebase, пользователи могут получать ссылки с недействительными ключами, что приведет к ошибкам auth/invalid-api-key.
Чтобы устранить эту проблему:
- Если вы используете Firebase Hosting, ключ API может быть сохранен в кеше
init.json. Разверните новую версию сайта хостинга (firebase deploy --only hosting), чтобы принудительно заставить сервис метаданных на сервере сгенерировать конфигурацию с активным ключом API. - Если нужно обновить сам ключ API для внутреннего сервиса. Поскольку сопоставление ключа API для внутреннего сервиса нельзя изменить напрямую с помощью консоли или SDK, вам нужно обратиться в службу поддержки и запросить обновление конфигурации аутентификации для внутреннего сервиса в вашем проекте.
Затем вам нужно настроить проект Firebase, чтобы он ссылался на ваш обработчик действий с электронной почтой в письмах для управления пользователями.
Как добавить ссылку на обработчик в шаблоны писем
Чтобы настроить проект Firebase для использования собственного обработчика действий с электронной почтой:
В консоли Firebase перейдите на вкладку Безопасность > Аутентификация > Шаблоны.
В любом из разделов Типы электронных писем нажмите на значок карандаша, чтобы изменить шаблон письма.
Нажмите Настроить URL действия и укажите URL обработчика действий с электронной почтой.
После сохранения URL он будет использоваться во всех шаблонах электронных писем проекта Firebase.