Search code examples
node.jsfirebase-authenticationgoogle-cloud-functionsfirebase-admin

Sending email confirmation and adding data to collection after creating user in Firebase


I've created a rest API for signup. The idea is to create the user using

admin.auth().createUser({...}) method and after getting the response send an email confirmation link to the email provided by the user.

Another thing that needs to be done is to create a collection called 'users' and add some user data to a document which will have the id equals to auth id.

Problem is my application is creating users just fine but I'm not getting any email confirmations nor the data is getting added to the collection.

CODE:

const functions = require("firebase-functions");
const admin =  require("firebase-admin");
const express = require("express");
const app = express();
const cors = require("cors")({origin: true});

admin.initializeApp();
const db = admin.firestore();


app.get("/hello-world", (req, res) => {
    res.send("Hello World!");
});


// create user with email and password with admin sdk
app.post("/signup", cors, (req, res) => {
    const email = req.body.email;
    const password = req.body.password;
    
    // check if email is a valid email
    if (!email || !email.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i)) {
        res.status(400).send("Invalid email");
        return;
    }
    
    admin.auth().createUser({
        email: email,
        password: password,
        emailVerified: false,
    }).then(function(userRecord) {
        admin.auth().sendEmailVerification(userRecord.uid).then(function() {
            res.send("User created");
        })
        return db.collection("users").doc(userRecord.uid).set({
            email: userRecord.email,
            password: userRecord.password,
            emailVerified: userRecord.emailVerified,
            username: "",
            firstName: "",
            lastName: "",
        });
    }).then(null, function(error) {
        res.status(400).send(error);
    })
});


exports.app = functions.https.onRequest(app);

Solution

  • The Admin SDK has no sendEmailVerification method. Although it has generateEmailVerificationLink() which can be used to generate a verification link, you would have to send the email yourself. You can try using Nodemailer or Firestore Trigger Email extension. Also the return statement would run before the email function so try handling the promises correctly. You can try using an async function as shown:

    app.post("/signup", cors, async (req, res) => {
      const email = req.body.email;
      const password = req.body.password;
    
      // check if email is a valid email
      if (!email || !email.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i)) {
        res.status(400).send("Invalid email");
        return;
      }
    
      const userRecord = await admin.auth().createUser({
        email: email,
        password: password,
        emailVerified: false,
      })
      // Custom function to generate link and send email
      // await sendVerificationEmail()
      await db.collection("users").doc(userRecord.uid).set({
        email: userRecord.email,
        password: userRecord.password,
        emailVerified: userRecord.emailVerified,
        username: "",
        firstName: "",
        lastName: "",
      });
      return res.sendStatus(200)
    });
    

    Other option would be to sign in users on client after /signup is completed and use sendVerificationEmail function using the client SDK.