Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send email verification after user creation with Firebase Cloud functions?

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!

like image 889
Davide Avatar asked Mar 18 '17 09:03

Davide


People also ask

How do I verify my email on Firebase authentication?

Enable Email Link sign-in for your Firebase projectIn the Firebase console, open the Auth section. On the Sign in method tab, enable the Email/Password provider. Note that email/password sign-in must be enabled to use email link sign-in. In the same section, enable Email link (passwordless sign-in) sign-in method.

How do I customize my Firebase verification email?

To customize your Firebase project's email action handler, you must create and host a web page that uses the Firebase JavaScript SDK to verify the request's validity and complete the request. Then, you must customize your Firebase project's email templates to link to your custom action handler.

Is Firebase email verification free?

Firebase Authentication service is free in all plans.


4 Answers

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.

like image 108
Frank van Puffelen Avatar answered Oct 26 '22 22:10

Frank van Puffelen


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.

like image 5
Rami H Avatar answered Oct 26 '22 21:10

Rami H


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.

like image 2
Abu Alfadl Avatar answered Oct 26 '22 23:10

Abu Alfadl


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.

like image 1
Renaud Tarnec Avatar answered Oct 26 '22 22:10

Renaud Tarnec