如何使用firebase-admin SDK在服务器上使用sendPasswordResetEmail()函数?

时间:2018-12-19 20:13:15

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

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

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

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

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

但是它仅为每个链接生成一个链接,通过唯一的emailVerification()为我提供服务,generatePasswordReset中的一个链接始终告诉我:

  

尝试再次重置密码

     

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

即使是新链接,也没有使用。

我的三个问题是:

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

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

3 个答案:

答案 0 :(得分:1)

  1. 这些功能在firebase-admin中不可用,但是您也应该能够在服务器上运行客户端SDK(firebase)。这并不是最佳做法,但可以完成工作。长期存在的open feature request支持Admin SDK中的此功能。您会在那里找到一些有用的提示和解决方法。
  2. 可能是一个错误。我会考虑将其报告为完整且最少的复制。 Admin SDK在此用例中确实有一个integration test case,但工作原理略有不同。
  3. 暂时不。希望当上述功能请求最终得到满足时,将涵盖此问题。

答案 1 :(得分:0)

这是此处提供的解决方法 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);
    }
  }
});

答案 2 :(得分:0)

我确定这不再重要了,但是我很头疼,所以即使不是最大的答案,我也想分享一下。

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