【问题标题】:How to use the sendPasswordResetEmail() function on the server using the firebase-admin SDK?如何使用 firebase-admin SDK 在服务器上使用 sendPasswordResetEmail() 函数?
【发布时间】:2019-05-20 09:02:21
【问题描述】:

过去,我在 web 客户端中使用 firebase.auth,一旦用户创建另一个用户,我会链接某些安全逻辑:

  • 创建用户后,我会发送一封电子邮件以验证您的电子邮件 使用函数 user.sendEmailVerification ()。
  • 由于该用户是由另一个用户创建的,因此我分配了一个默认密码 并使用 sendPasswordResetEmail() 函数让用户 注册他的新密码。

到目前为止,这对我来说效果很好,但是现在 出于多种原因,我需要将该逻辑移至我的服务器,因为我正在开发具有云功能的后端并且我正在使用Node.js Firebase Admin SDK 版本 6.4.0,但我找不到使用 user.sendEmailVerification() 和 sendPasswordResetEmail() 的功能在服务器上实现相同逻辑的方法,我发现最接近的是:

  • auth.generateEmailVerificationLink(电子邮件)
  • auth.generatePasswordResetLink(电子邮件)

但它只会为每个链接生成一个链接,顺便说一下,唯一的 emailVerification() 为我服务,generatePasswordReset 的链接总是告诉我:

再次尝试重置密码

您的密码重置请求已过期或链接已过期 已经用过了。

虽然是新的链接,但没有被使用过。

我的 3 个问题是:

  1. 如何使 sendEmailVerification () 和 sendPasswordResetEmail() 函数在服务器上工作吗?
  2. 如何使生成的链接使用 auth.generatePasswordResetLink(电子邮件)在服务器上正常工作吗?
  3. 有没有办法使用服务器上的模板和电子邮件 在 firebase 身份验证中?

提前感谢您与我分享您的经验,以及所有程序员社区的堆栈溢出。

【问题讨论】:

  • 尚不清楚您要在这里完成什么。您声称您正在让一个用户创建另一个用户,但不清楚正在验证谁的电子邮件以及正在重置哪个用户的密码。请提供一个清晰的流程并对每个用户的电子邮件进行不同的标记,以便我们将它们区分开来。

标签: firebase firebase-authentication google-cloud-functions firebase-admin


【解决方案1】:
  1. firebase-admin 中没有这些功能,但您应该也可以在服务器上运行客户端 SDK (firebase)。不完全是最佳实践,但它会完成工作。在 Admin SDK 中有一个长期存在的 open feature request 来支持此功能。您会在此处找到一些有用的提示和解决方法。
  2. 可能是一个错误。我会考虑将其与完整且最少的复制一起报告。对于这个用例,Admin SDK 确实有一个 integration test case,但它的工作方式略有不同。
  3. 暂时没有。希望最终满足上述功能要求时,这将得到解决。

【讨论】:

【解决方案2】:

这是此处提供的解决方法 https://github.com/firebase/firebase-admin-node/issues/46

我找到了一个非常适合我的用例的解决方法,见下文。我不确定这是否是最佳实践,但我想保持服务器和客户端请求之间的电子邮件完全相同。很想听听这个实现的任何缺陷?



As suggested above, it uses a three step process to do this:

Acquire a custom token via the admin sdk's createCustomToken(uid)
It converts this custom token to an idToken via the API
It invokes the send email verification endpoint on the API
const functions = require('firebase-functions');
const fetch = require('node-fetch');
const admin = require('firebase-admin');

const apikey = functions.config().project.apikey;
const exchangeCustomTokenEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${apikey}`;
const sendEmailVerificationEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${apikey}`;

module.exports = functions.auth.user().onCreate(async (user) => {
  if (!user.emailVerified) {
    try {
      const customToken = await admin.auth().createCustomToken(user.uid);

      const { idToken } = await fetch(exchangeCustomTokenEndpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          token: customToken,
          returnSecureToken: true,
        }),
      }).then((res) => res.json());

      const response = await fetch(sendEmailVerificationEndpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          requestType: 'VERIFY_EMAIL',
          idToken: idToken,
        }),
      }).then((res) => res.json());

      // eslint-disable-next-line no-console
      console.log(`Sent email verification to ${response.email}`);
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }
});

【讨论】:

    【解决方案3】:

    我确信这不再重要了,但是我这样做很头疼,所以即使这不是最好的答案,我也想分享。

    await admin.auth().createUser(
                {email, password, displayName, phoneNumber, photoURL}
            ).then(function(userRecord) {
                admin.auth().createCustomToken(userRecord.uid).then(function(customToken){
                    createdToken=customToken; 
                    firebase.auth().signInWithCustomToken(createdToken).catch(function(error){
                        return console.log(error)
                    })
                    firebase.auth().onAuthStateChanged(function(user) {
                        user.sendEmailVerification().then(function(){
                            return console.log('It worked')
                        },function(error) {
                            return console.log(error)
                        })
                      });
                })
            })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      • 2020-11-17
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      相关资源
      最近更新 更多