Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Functions for Firebase - action on email verified

Im trying to create a Cloud Function trigger that will execute after email has been verified.

In the Cloud Functions samples I could only find examples on triggers for onCreate and onDelete.

Within the documentation I found something about creating custom action handlers but I don't actually want to replace the standard email verification dialog they have by default, I just want to change the property of a "user" after the email is verified.

Does anyone have any experience with this, and is this even possible? Or is my only option to create my custom verification view/dialog webpage?

like image 217
deloki Avatar asked Apr 19 '17 18:04

deloki


People also ask

Does Firebase charge for email verification?

So you don't pay for verifying an email address, nor for each API call you make, but only for completed verifications through the code that was sent in the SMS message.

Where you can edit the email template of email address verification in Firebase?

Open your project in the Firebase console. Go to the Email Templates page in the Auth section. In any of the Email Types entries, click the pencil icon to edit the email template.


2 Answers

I faced this problem and took me a long time to figure it out how to solve so I hope this could help anyone that could get stuck into this too:

1 -> I created a function that was triggered with onCreate() for a new user

exports.sendConfirmationEmail = functions.auth.user()
                    .onCreate((user) => {
                        const actionCodeSettings = {
                            url: 'https://appNextURL.com/',
                            handleCodeInApp: false//ensure that the link will open into browser
                        };
                        return admin.auth().generateEmailVerificationLink(user.email, actionCodeSettings)
                            .then(async (link) => {
                                await db.collection('users').doc(user.uid).set({
                                    verificationLink: link,
                                    emailVerified: false
                                }, {merge: true});
                                return sendCustomVerificationEmail(user.email, user.displayName, link);
                            })
                            .catch((err) => {
                                console.error("Error:", err);
                                return Promise.reject(err);
                            });
                    });
  • The generateEmailVErificationLink() will generate the link based on the link we will save on step 3.

  • The function sendCustomVerificationEmail() is just an internal function that overcomes the standard email firebase send

2 -> Then I created a function that will receive a manual http trigger with the data that would be generated automatically by firebase when sending an automatic email

exports.verifyEmail = functions.https.onRequest((req, res) => {
                        const {mode, oobCode, apiKey, continueUrl, lang} = req.query;
                        const link = "https://us-central1-projectId.cloudfunctions.net/verifyEmail/?mode=" + encodeURIComponent(mode) + "&oobCode=" + encodeURIComponent(oobCode) + "&apiKey=" + encodeURIComponent(apiKey) + "&continueUrl=" + encodeURIComponent(continueUrl) + "&lang=" + encodeURIComponent(lang);
                        return db.collection("users")
                            .where("verificationLink", "==", link)
                            .get()
                            .then(function (querySnapshot) {
                                querySnapshot.forEach(function (user) {
                                    const userData: UserData = user.data();
                                    console.log("email verified: ", userData.userId);
                                    return admin.auth().updateUser(userData.userId, {
                                        emailVerified: true
                                    }).then(function (userRecord) {
                                        return db.collection('users').doc(userData.userId).set({emailVerified: true}, {merge: true});
                                    });
                                });
                                return res.sendStatus(200).end();
                            }).catch(function (err) {
                                console.log("error:", err);
                                return res.sendStatus(403).end();
                            });
                    });
  • As I saved the link in the onCreate() I can now query that link to get who is the user that I am authenticating

3 -> the third step is to change the link in to Firebase Authentication template to the link generated into the 2nd step:

Navigate to Authentication>Templates:

  • Click on edit icon> Click on customize action URL:

  • Navigation

  • Paste the link generated into the step 2 and save:

  • Save link

Now every link generated automatically will go trought that function you created on step 2 and you will be able to handle the actions you want to happen.

I hope I could be clear.

like image 88
Rodrigo S Avatar answered Oct 13 '22 17:10

Rodrigo S


you could still check for the verification status (at least) on Android with interface UserInfo method isEmailVerified(); eg. in order to send another verification email upon successful login, in case the current user has not yet verified the email address - and show the login screen again. one could as well HTTP trigger a cloud function or update values in the Firebase directly, through the client library. this might also apply to other platform clients, where one can check for the verification status.

this would not be exactly the event when the email just had been verified, but upon each single login attempt one knows the verification status and this value might be merely relevant on the client-side.

like image 2
Martin Zeitler Avatar answered Oct 13 '22 16:10

Martin Zeitler