Cloud Functions for Firebase - 已验证电子邮件操作

Posted

技术标签:

【中文标题】Cloud Functions for Firebase - 已验证电子邮件操作【英文标题】:Cloud Functions for Firebase - action on email verified 【发布时间】:2017-09-16 03:13:51 【问题描述】:

我正在尝试创建一个云函数触发器,该触发器将在验证电子邮件后执行。

在Cloud Functions samples 中,我只能找到onCreateonDelete 的触发器示例。

在the documentation 中,我发现了一些关于创建自定义操作处理程序的内容,但我实际上并不想替换他们默认拥有的标准电子邮件验证对话框,我只想在电子邮件之后更改“用户”的属性已验证。

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

【问题讨论】:

很遗憾,您不能在电子邮件验证中使用云函数触发器。该团队正在考虑使这成为可能,因为它已被多次要求。也请通过功能请求投票:firebase.google.com/support/contact/bugs-features 有一个用于删除未使用帐户的函数示例脚本。您可以对其进行调整以每隔一段时间检查帐户并检查所有经过验证的电子邮件:github.com/firebase/functions-samples/tree/master/… 也许这会有所帮助。 @DougStevenson 是否有一些官方方式可以对特定功能请求进行投票?类似于 Google 问题跟踪器,人们可以在其中为功能加注星标like this one。 @DougStevenson 从 3 年前开始,这个功能有进步吗?目前正在寻找类似的东西,并在此处偶然发现了您的评论。 【参考方案1】:

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

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);
                            );
                    );

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();
                            );
                    );
当我将链接保存在 onCreate() 中后,我现在可以查询该链接以获取我正在验证的用户是谁

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

导航到身份验证>模板:

点击编辑图标>点击自定义操作网址:

Navigation

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

Save link

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

我希望我能说清楚。

【讨论】:

我正在查看您的答案,想知道您的 sendCustomVerificationEmail 是什么样的?干杯! 但是如果用户想要重新发送 url,在这种情况下会生成一个新的 url,那么您将拥有与您在 onCreate 中保存的不同的 url。在这种情况下,查询将不起作用。 !!!安全漏洞!!!我认为存储验证链接的文档应该作为单独的集合,没有任何用户访问,例如“电子邮件验证”。按照您的方式,用户可以通过简单地使用验证链接获取他的用户数据来验证电子邮件。而不是打开电子邮件。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

创建一个发布按钮,以便您的用户触发您的云功能

我没有在 auth.emailVerified 后立即触发云功能,而是为我的用户提供了一个“发布配置文件”按钮,该按钮触发了一个 http 云功能(传入 user.uid)。此函数使用传入的 user.uid 查找用户身份验证

如果 user.uid && auth.emailVerified

将 auth.emailVerified 写入每个 user.post

默认情况下,发布文档“post.emailVerified”字段以 false 开头,并且只能通过云功能中的 adminFirestore 写入。

【讨论】:

我不认为给用户带来最糟糕的体验是解决技术挑战的正确方法。

以上是关于Cloud Functions for Firebase - 已验证电子邮件操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现

如何使用 Google Python Client for Cloud Functions 获取 Google Cloud Functions 列表?

Cloud Functions for Firebase 超时

Cloud Functions for Firebase onWrite 超时

在 Cloud Functions for Firebase 中访问 db 数据

Cloud Functions for Firebase 组织