某些用户管理操作(例如更新用户的电子邮件地址和重置用户的密码)会导致向用户发送电子邮件。这些电子邮件包含收件人可以打开以完成或取消用户管理操作的链接。默认情况下,用户管理电子邮件链接到默认操作处理程序,该处理程序是托管在项目 Firebase 托管域中的 URL 上的网页。
您可以改为创建和托管自定义电子邮件操作处理程序来执行自定义处理并将电子邮件操作处理程序与您的网站集成。
以下用户管理操作要求用户使用电子邮件操作处理程序完成操作:
- 重置密码
- 撤销电子邮件地址更改——当用户更改其帐户的主要电子邮件地址时,Firebase 会向他们的旧地址发送一封电子邮件,以便他们撤消更改
- 验证电子邮件地址
要自定义 Firebase 项目的电子邮件操作处理程序,您必须创建并托管一个网页,该网页使用 Firebase JavaScript SDK 来验证请求的有效性并完成请求。然后,您必须自定义 Firebase 项目的电子邮件模板以链接到您的自定义操作处理程序。
创建电子邮件操作处理程序页面
Firebase 在生成用户管理电子邮件时会向您的操作处理程序网址添加几个查询参数。例如:
https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr
这些参数指定用户正在完成的用户管理任务。您的电子邮件操作处理程序页面必须处理以下查询参数:
参数 模式 要完成的用户管理操作。可以是以下值之一:
-
resetPassword
-
recoverEmail
-
verifyEmail
oob代码 一次性代码,用于识别和验证请求 apiKey 您的 Firebase 项目的 API 密钥,为方便起见而提供 继续网址 这是一个可选的 URL,它提供了一种通过 URL 将状态传递回应用程序的方法。这与密码重置和电子邮件验证模式有关。发送密码重置电子邮件或验证电子邮件时,需要使用继续 URL 指定 ActionCodeSettings
对象,以使其可用。这使得用户可以在电子邮件操作后从中断的地方继续。郎 这是表示用户区域设置的可选BCP47语言标记(例如
fr
)。您可以使用此值向您的用户提供本地化的电子邮件操作处理程序页面。本地化可以通过 Firebase 控制台设置,也可以通过在触发电子邮件操作之前调用相应的客户端 API 来动态设置。例如,使用 JavaScript:
firebase.auth().languageCode = 'fr';
.为获得一致的用户体验,请确保电子邮件操作处理程序本地化与电子邮件模板匹配。
以下示例显示了如何在基于浏览器的处理程序中处理查询参数。 (您也可以使用类似的逻辑将处理程序实现为 Node.js 应用程序。)
Web version 9
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': "YOU_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 version 8
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 version 9
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 version 8
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 version 9
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 version 8
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 version 9
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 version 8
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 。
接下来,您必须将 Firebase 项目配置为在其用户管理电子邮件中链接到您的自定义电子邮件操作处理程序。
链接到您的电子邮件模板中的自定义处理程序
要将您的 Firebase 项目配置为使用您的自定义电子邮件操作处理程序:
- 在Firebase 控制台中打开您的项目。
- 转到身份验证部分的电子邮件模板页面。
- 在任何电子邮件类型条目中,单击铅笔图标以编辑电子邮件模板。
- 单击自定义操作 URL ,并指定您的自定义电子邮件操作处理程序的 URL。
保存 URL 后,您的所有 Firebase 项目的电子邮件模板都将使用它。