11
votes

I'm trying to send the verification email after the user is created. Since there's no way on Firebase itself, I'm trying it with cloud functions.

I cannot really find a lot of documentation about it. What I tried to do so far is:

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

But I get the error that user is not defined.

How can I create this function?

Thanks!

5
Did you find the solution?wonsuc
No, I switched to couchbaseDavide

5 Answers

16
votes

There are two possibilities to send an "email verification" email to a user:

  1. The signed-in user requests that a verification email be sent. For that, you call, from the front-end, the sendEmailVerification() method from the appropriate Client SDK.
  2. Through one of the Admin SDKs, you generate a link for email verification via the corresponding method (e.g. auth.generateEmailVerificationLink() for the Node.js Admin SDK) and you send this link via an email sent through your own mechanism. All of that is done in the back-end, and can be done in a Cloud Function.

Note that the second option with the Admin SDKs is not exactly similar to the first option with the Client SDKs: in the second option you need to send the email through your own mechanism, while in the first case, the email is automatically sent by the Firebase platform

If you'd like that ability to be added to the Admin SDK, I'd recommend you file a feature request.

5
votes

This is how I implemented it successfully using Firebase cloud functions along with a small express backend server

Firebase Cloud function (background) triggered with every new user created

  • This function sends a "user" object to your api endpoint

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

Server Middleware code

  • verifyEmail here is used as middleware

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

Server code

// 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()
})

This endpoint will return back the full user object and will send the verification email to user.

I hope this helps.

2
votes

First view the documentation by Firebase here.

As the registration phase completes and result in success, trigger the following function asynchronously :

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

The user will now be provided with a verification Email. Upon clicking the hyper linked the user will be verified by your project server with Firebase.

enter image description here

How do you determine whether or not a user did verify their Email?

 private void checkEmail() {

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

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

Sadly, you may not customize the content/body of your verification Email ( I have been heavily corresponding with Firebase to provide alternative less hideous looking templates ). You may change the title or the message sender ID, but that's all there is to it.

Not unless you relink your application with your own supported Web. Here.

1
votes

Since the release of the Version 6.2.0 of the Node.js Admin SDK on November 19, 2018 it is possible to generate, in a Cloud Function, a link for email verification via the auth.generateEmailVerificationLink() method.

You will find more details and some code samples in the documentation.

You can then send an email containing this link via Mailgun, Sendgrid or any other email microservice. You'll find here a Cloud Function sample that shows how to send an email from a Cloud Function.

-1
votes

If you want to let Admin SDK do it, as of now there is no option other than generating the email verification link and sending with your own email delivery system.

However

You can write a REST request on cloud functions and initiate the email verification mail this way.

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
}

As soon as you signup, pass the access token to this method and it should send a mail to the signup user.

apiKey : Is the "Web API key" listed in General tab of your project settings in firebase console access token : Access token of the current user (I use signup rest api internally so there is an option to request token in response)