使用 Firebase Cloud 功能创建用户后如何发送电子邮件验证?

Posted

技术标签:

【中文标题】使用 Firebase Cloud 功能创建用户后如何发送电子邮件验证?【英文标题】:How to send email verification after user creation with Firebase Cloud functions? 【发布时间】:2017-08-09 21:37:17 【问题描述】:

我正在尝试在创建用户后发送验证电子邮件。由于 Firebase 本身没有办法,我正在尝试使用云功能。

我真的找不到很多关于它的文档。到目前为止,我尝试做的是:

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

但我得到了用户未定义的错误。

如何创建这个函数?

谢谢!

【问题讨论】:

找到解决方案了吗? 不,我换成了沙发床 【参考方案1】:

向用户发送“电子邮件验证”电子邮件有两种可能性:

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

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

如果您希望将该功能添加到 Admin SDK,我建议您使用file a feature request。

【讨论】:

谢谢。这使得 Firebase 在生产阶段毫无用处。我将提交功能请求,但我也会评估 Firebase 的替代方案。 另一种解决方案:medium.com/@treviergits/… 我想我会在用户第一次登录时发送它! 这试图解释 Admin SDK 中没有 sendVerificationEmailToUser(uid) 方法,以及为什么会这样。我试图澄清一下,但如果你有更好的词,请编辑(这里还是凌晨?)。 对“残酷”的唤醒感到抱歉! ? 我会在今天晚些时候调整它!【参考方案2】:

这就是我使用 Firebase 云功能和小型快速后端服务器成功实现它的方式

每创建一个新用户都会触发 Firebase Cloud 功能(背景)

此函数将“用户”对象发送到您的 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 不会将此注册为用户登录?【参考方案3】:

首先查看 Firebase here 的文档。

随着注册阶段完成并成功,异步触发以下函数:

 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 验证用户。

您如何确定用户是否验证了他们的电子邮件?

 private void checkEmail() 

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

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

遗憾的是,您可能无法自定义验证电子邮件的内容/正文(我一直与 Firebase 密切相关,以提供其他看起来不那么丑陋的模板)。您可以更改标题或消息发件人 ID,但仅此而已。

除非您将应用程序与您自己支持的 Web 重新链接,否则不会。 Here.

【讨论】:

谢谢,但我说的是 Firebase 云,而不是 android。我发现发送验证电子邮件的是客户端本身,这让我非常失望。它应该来自后端。 您希望验证邮件在用户注册正确的同时触发和发送?【参考方案4】:

自 2018 年 11 月 19 日发布 Version 6.2.0 of the Node.js Admin SDK 以来,可以在云函数中通过 auth.generateEmailVerificationLink() 方法生成用于电子邮件验证的链接。

您将在documentation 中找到更多详细信息和一些代码示例。

然后,您可以通过 Mailgun、Sendgrid 或任何其他电子邮件微服务发送包含此链接的电子邮件。您会在此处找到 Cloud Function sample,它展示了如何从云函数发送电子邮件。

【讨论】:

【参考方案5】:

如果您想让 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 密钥” 访问令牌:当前用户的访问令牌(我在内部使用注册休息API,因此可以选择请求令牌作为响应)

【讨论】:

以上是关于使用 Firebase Cloud 功能创建用户后如何发送电子邮件验证?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Angular 和 Firebase 登录后获取用户配置文件

使用 Cloud Functions for Firebase 发送推送通知

Cloud Functions for Firebase - 创建新用户时写入数据库

Firebase Cloud Firestore 在 asia-south1(孟买)不可用?

使用 Firebase 对 GCP Cloud 函数进行双重定价

我可以在 Cloud Functions Http Trigger 中的 Firebase 身份验证上创建用户吗?