Firebase的云功能 - 验证电子邮件的操作

del*_*oki 29 firebase firebase-authentication google-cloud-functions

我试图创建一个云功能触发器,它将在验证电子邮件后执行.

Cloud Functions示例中,我只能找到关于onCreate和的触发器的示例onDelete.

文档中,我发现了一些关于创建自定义操作处理程序的内容,但我实际上并不想要替换默认情况下的标准电子邮件验证对话框,我只想在验证电子邮件后更改"用户"的属性.

有没有人有这方面的经验,这甚至可能吗?或者我是创建自定义验证视图/对话框网页的唯一选择?

Rod*_*o S 14

我遇到了这个问题,花了很长时间才弄清楚如何解决,所以我希望这可以帮助任何可能陷入困境的人:

1 -> 我为新用户创建了一个由 onCreate() 触发的函数

exports.sendConfirmationEmail = functions.auth.user()
                    .onCreate((user) => {
                        const actionCodeSettings = {
                            url: 'https://appNextURL.com/',
                            handleCodeInApp: false//ensure that the link will open into browser
                        };
                        return admin.auth().generateEmailVerificationLink(user.email, actionCodeSettings)
                            .then(async (link) => {
                                await db.collection('users').doc(user.uid).set({
                                    verificationLink: link,
                                    emailVerified: false
                                }, {merge: true});
                                return sendCustomVerificationEmail(user.email, user.displayName, link);
                            })
                            .catch((err) => {
                                console.error("Error:", err);
                                return Promise.reject(err);
                            });
                    });
Run Code Online (Sandbox Code Playgroud)
  • generateEmailVErificationLink() 将根据我们将在步骤 3 中保存的链接生成链接。

  • 函数 sendCustomVerificationEmail() 只是一个内部函数,它克服了标准的电子邮件 firebase 发送

2 -> 然后我创建了一个函数,该函数将接收一个手动 http 触发器,其中包含在发送自动电子邮件时由 firebase 自动生成的数据

exports.verifyEmail = functions.https.onRequest((req, res) => {
                        const {mode, oobCode, apiKey, continueUrl, lang} = req.query;
                        const link = "https://us-central1-projectId.cloudfunctions.net/verifyEmail/?mode=" + encodeURIComponent(mode) + "&oobCode=" + encodeURIComponent(oobCode) + "&apiKey=" + encodeURIComponent(apiKey) + "&continueUrl=" + encodeURIComponent(continueUrl) + "&lang=" + encodeURIComponent(lang);
                        return db.collection("users")
                            .where("verificationLink", "==", link)
                            .get()
                            .then(function (querySnapshot) {
                                querySnapshot.forEach(function (user) {
                                    const userData: UserData = user.data();
                                    console.log("email verified: ", userData.userId);
                                    return admin.auth().updateUser(userData.userId, {
                                        emailVerified: true
                                    }).then(function (userRecord) {
                                        return db.collection('users').doc(userData.userId).set({emailVerified: true}, {merge: true});
                                    });
                                });
                                return res.sendStatus(200).end();
                            }).catch(function (err) {
                                console.log("error:", err);
                                return res.sendStatus(403).end();
                            });
                    });
Run Code Online (Sandbox Code Playgroud)
  • 当我在 onCreate() 中保存链接时,我现在可以查询该链接以获取我正在验证的用户是谁

3 -> 第三步是将 Firebase Authentication 模板中的链接更改为第二步中生成的链接:

导航到身份验证>模板:

  • 单击编辑图标> 单击自定义操作 URL:

  • 导航

  • 将生成的链接粘贴到步骤 2 中并保存:

  • 保存链接

现在自动生成的每个链接都将使用您在第 2 步中创建的功能,您将能够处理您想要发生的操作。

我希望我能说清楚。

  • !!! 安全漏洞!!!我认为存储验证链接的文档应该作为单独的集合,没有任何用户访问权限,例如“emailVerification”。按照您的方式,用户只需通过验证链接获取其用户数据即可验证电子邮件。而不是打开电子邮件。 (6认同)
  • 但是,如果用户想要重新发送 url,在这种情况下会生成一个新的 url,那么您将得到一个与 onCreate 中保存的 url 不同的 url。在这种情况下,查询将不起作用。 (2认同)

Mar*_*ler 3

您仍然可以(至少)在 Android 上使用接口UserInfo方法检查验证状态isEmailVerified();例如。为了在成功登录后发送另一封验证电子邮件,以防当前用户尚未验证电子邮件地址 - 并再次显示登录屏幕。人们还可以通过客户端库通过 HTTP 触发云函数或直接更新 Firebase 中的值。这可能也适用于其他平台客户端,可以在其中检查验证状态。

这并不完全是电子邮件刚刚被验证时的事件,但在每次登录尝试时,人们都会知道验证状态,并且该值可能仅与客户端相关。