如何通过Firebase Cloud functions在用户创建后发送电子邮件验证?

13

我正在尝试在用户创建后发送验证电子邮件。由于 Firebase 本身没有提供此功能,因此我正在尝试使用云函数来实现。

我真的找不到太多关于它的文档。目前我所尝试的是:

exports.sendEmailVerification = functions.auth.user().onCreate(event => {
    return user.sendEmailVerification()
});

但是我收到了"user未定义"的错误提示。

我该如何创建这个函数呢?

谢谢!


你找到解决方案了吗? - wonsuc
4
不,我切换到Couchbase。 - Davide
5个回答

18

有两种方法向用户发送“电子邮件验证”电子邮件:

  1. 登录的用户请求发送验证电子邮件。为此,您可以从前端调用相应客户端SDK中的sendEmailVerification()方法。
  2. 通过其中一个Admin SDK,您可以通过相应的方法(例如Node.js Admin SDK的auth.generateEmailVerificationLink()生成电子邮件验证链接 并且 通过您自己的机制发送此链接的电子邮件。所有这些都在后端完成,并且可以在Cloud Function中完成。

请注意,使用Admin SDK的第二种选项与使用Client SDK的第一种选项不完全相同:在第二种选项中,您需要通过自己的机制发送电子邮件,而在第一种情况下,Firebase平台会自动发送电子邮件。

如果您希望将此功能添加到Admin SDK中,我建议您提交一个功能请求

9
谢谢。这让 Firebase 在生产阶段变得几乎无用。我会提出一个功能请求,但也会评估 Firebase 的替代方案。 - Davide
1
另一种解决方案:https://medium.com/@treviergits/firebase-nodejs-email-verification-from-cloud-functions-f4d3f2ece31a - Egghead
2
我想我会在用户第一次登录时发送它! - Rami Alloush
1
这篇文章试图解释为什么在Admin SDK中没有sendVerificationEmailToUser(uid)方法。我尝试着澄清一下,但如果您有更好的措辞,请编辑一下(因为现在还很早)。 - Frank van Puffelen
1
抱歉让你受了“惊吓”!我今天稍后会进行调整! - Renaud Tarnec
显示剩余5条评论

6

下面是我如何成功使用Firebase云函数和一个小的Express后端服务器实现它的方法

Firebase云函数 (background) 每当新用户被创建时触发

  • 此函数将一个 "user" 对象发送到您的api端点

const functions = require('firebase-functions');
const fetch = require('node-fetch');

// Send email verification through express server
exports.sendVerificationEmail = functions.auth.user().onCreate((user) => {
  // Example of API ENPOINT URL 'https://mybackendapi.com/api/verifyemail/'
  return fetch( < API ENDPOINT URL > , {
      method: 'POST',
      body: JSON.stringify({
        user: user
      }),
      headers: {
        "Content-Type": "application/json"
      }
    }).then(res => console.log(res))
    .catch(err => console.log(err));
});

服务器中间件代码

  • 这里的verifyEmail被用作中间件

// File name 'middleware.js'
import firebase from 'firebase';
import admin from 'firebase-admin';

// Get Service account file from firebase console
// Store it locally - make sure not to commit it to GIT
const serviceAccount = require('<PATH TO serviceAccount.json FILE>');
// Get if from Firebase console and either use environment variables or copy and paste them directly
// review security issues for the second approach
const config = {
  apiKey: process.env.APIKEY,
  authDomain: process.env.AUTHDOMAIN,
  projectId: process.env.PROJECT_ID,
};
// Initialize Firebase Admin
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// Initialize firebase Client
firebase.initializeApp(config);

export const verifyEmail = async(req, res, next) => {
  const sentUser = req.body.user;
  try {
    const customToken = await admin.auth().createCustomToken(sentUser.uid);
    await firebase.auth().signInWithCustomToken(customToken);
    const mycurrentUser = firebase.auth().currentUser;
    await mycurrentUser.sendEmailVerification();
    res.locals.data = mycurrentUser;
    next();
  } catch (err) {
    next(err);
  }
};

服务器代码

// Filename 'app.js'
import express from 'express';
import bodyParser from 'body-parser';
// If you don't use cors, the api will reject request if u call it from Cloud functions
import cors from 'cors';
import {
  verifyEmail
} from './middleware'

app.use(cors());
app.use(bodyParser.urlencoded({
  extended: true,
}));
app.use(bodyParser.json());

const app = express();
// If you use the above example for endpoint then here will be
// '/api/verifyemail/'
app.post('<PATH TO ENDPOINT>', verifyEmail, (req, res, next) => {
  res.json({
    status: 'success',
    data: res.locals.data
  });
  next()
})

此端点将返回完整的用户对象,并向用户发送验证电子邮件。

希望这可以帮到您。


这是否也显示为用户已登录?还是Firebase Auth不将其注册为用户登录? - Kevin Danikowski

2
首先查看Firebase文档此处
注册阶段完成并成功后,异步触发以下函数:
 private void sendVerification() {
             FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
             user.sendEmailVerification().addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                         system.print.out("Verification Email sent Champion")
                          }
                         }
                });
}

用户现在将收到一封验证电子邮件。点击超链接后,用户将通过Firebase被您的项目服务器验证。

enter image description here

你如何确定用户是否已验证他们的电子邮件?
 private void checkEmail() {

    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();

    if (user.isEmailVerified()) {
           // email verified ...
    } else {
       // error : email not verified ...
    }
}

很遗憾,您不能自定义验证电子邮件的内容/正文(我一直在与Firebase密切合作,以提供其他外观不那么丑陋的模板)。您可以更改标题或消息发送者ID,但这就是全部。

除非您使用自己支持的Web重新链接应用程序。在这里


1
谢谢,但我说的是使用Firebase云,而不是Android。我发现客户端本身发送验证电子邮件非常令人失望。它应该来自后端。 - Davide
你希望当用户正确注册时,验证电子邮件能够立即触发和发送,对吗? - Khaledonia

1

-1

如果您想让Admin SDK来完成这个任务,目前除了生成电子邮件验证链接并使用自己的电子邮件传递系统发送之外,没有其他选项。

然而

您可以编写一个云函数上的REST请求,并以此方式启动电子邮件验证邮件。

export async function verifyEmail(apiKey : string, accessToken : string) {
    // Create date for POST request
    const options = {
        method: 'POST',
        url: 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode',
        params: {
            key: apiKey
        },
        data: {
            requestType     : "VERIFY_EMAIL",
            idToken         : accessToken
        }
    };

    return await processRequest(options); //This is just to fire the request
}


一旦您注册成功,请将访问令牌传递给此方法,它应该向注册用户发送电子邮件。 apiKey:是Firebase控制台中项目设置的“常规”选项卡中列出的“Web API密钥” access token:当前用户的访问令牌(我在内部使用注册rest api,因此有一个请求响应中的令牌选项)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接