From b87ceec5937c3f5fae8d829baeb5474d8881e157 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Tue, 31 Mar 2026 18:55:37 +0000 Subject: [PATCH 1/5] Add beforeSendEmail and beforeSendSms blocking functions samples --- .../functions/index.js | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Node/quickstarts/auth-blocking-functions/functions/index.js b/Node/quickstarts/auth-blocking-functions/functions/index.js index d6ef1c4beb..e6fba7a411 100644 --- a/Node/quickstarts/auth-blocking-functions/functions/index.js +++ b/Node/quickstarts/auth-blocking-functions/functions/index.js @@ -17,9 +17,11 @@ const { beforeUserCreated, beforeUserSignedIn, + beforeEmailSent, + beforeSmsSent, HttpsError, } = require("firebase-functions/identity"); -const {admin} = require("firebase-admin"); +const admin = require("firebase-admin"); admin.initializeApp(); const db = admin.firestore(); @@ -68,3 +70,44 @@ exports.checkforban = beforeUserSignedIn(async (event) => { // [END v2bannedHttpsError] }); // [START v2CheckForBan] + +// [START v2CheckEmailDomain] +// [START v2beforeEmailSentFunctionTrigger] +// Block email sending with any non-acme email address. +exports.checkemaildomain = beforeEmailSent((event) => { + // [END v2beforeEmailSentFunctionTrigger] + // [START v2readEmailUser] + // Email passed in from the CloudEvent. + const email = event.data?.email || event.additionalUserInfo?.email; + // [END v2readEmailUser] + + // [START v2emailHttpsError] + // Only users of a specific domain can receive emails. + if (!email?.includes("@acme.com")) { + // Throw an HttpsError so that Firebase Auth rejects the email sending. + throw new HttpsError("invalid-argument", "Unauthorized email"); + } + // [END v2emailHttpsError] +}); +// [END v2CheckEmailDomain] + +// [START v2CheckPhoneNumber] +// [START v2beforeSmsSentFunctionTrigger] +// Block SMS sending with any non-US phone number. +exports.checkphonenumber = beforeSmsSent((event) => { + // [END v2beforeSmsSentFunctionTrigger] + // [START v2readSmsUser] + // Phone number passed from the CloudEvent. + const phoneNumber = event.data?.phoneNumber || + event.additionalUserInfo?.phoneNumber; + // [END v2readSmsUser] + + // [START v2smsHttpsError] + // Only users of a specific region can receive SMS. + if (!phoneNumber?.startsWith("+1")) { + // Throw an HttpsError so that Firebase Auth rejects the SMS sending. + throw new HttpsError("invalid-argument", "Unauthorized phone number"); + } + // [END v2smsHttpsError] +}); +// [END v2CheckPhoneNumber] From 928a8002eaf3132fdc77787ad57c84326b901eb2 Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Fri, 3 Apr 2026 13:03:42 -0500 Subject: [PATCH 2/5] Address PR comments for more a more targeted sample --- .../functions/index.js | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Node/quickstarts/auth-blocking-functions/functions/index.js b/Node/quickstarts/auth-blocking-functions/functions/index.js index e6fba7a411..8e2d198c45 100644 --- a/Node/quickstarts/auth-blocking-functions/functions/index.js +++ b/Node/quickstarts/auth-blocking-functions/functions/index.js @@ -29,7 +29,7 @@ const db = admin.firestore(); // [START v2ValidateNewUser] // [START v2beforeCreateFunctionTrigger] // Block account creation with any non-acme email address. -exports.validatenewuser = beforeUserCreated((event) => { +exports.validateNewUser = beforeUserCreated((event) => { // [END v2beforeCreateFunctionTrigger] // [START v2readUserData] // User data passed in from the CloudEvent. @@ -49,7 +49,7 @@ exports.validatenewuser = beforeUserCreated((event) => { // [START v2CheckForBan] // [START v2beforeSignInFunctionTrigger] // Block account sign in with any banned account. -exports.checkforban = beforeUserSignedIn(async (event) => { +exports.checkForBan = beforeUserSignedIn(async (event) => { // [END v2beforeSignInFunctionTrigger] // [START v2readEmailData] // Email passed from the CloudEvent. @@ -74,7 +74,7 @@ exports.checkforban = beforeUserSignedIn(async (event) => { // [START v2CheckEmailDomain] // [START v2beforeEmailSentFunctionTrigger] // Block email sending with any non-acme email address. -exports.checkemaildomain = beforeEmailSent((event) => { +exports.checkEmailDomain = beforeEmailSent((event) => { // [END v2beforeEmailSentFunctionTrigger] // [START v2readEmailUser] // Email passed in from the CloudEvent. @@ -83,9 +83,12 @@ exports.checkemaildomain = beforeEmailSent((event) => { // [START v2emailHttpsError] // Only users of a specific domain can receive emails. - if (!email?.includes("@acme.com")) { + if (!email) { // Throw an HttpsError so that Firebase Auth rejects the email sending. - throw new HttpsError("invalid-argument", "Unauthorized email"); + throw new HttpsError("invalid-argument", "No email was found in the CloudEvent"); + } + if (!email.endsWith("@acme.com")) { + throw new HttpsError("permission-denied", "Only users from the acme.com domain can authenticate"); } // [END v2emailHttpsError] }); @@ -93,8 +96,13 @@ exports.checkemaildomain = beforeEmailSent((event) => { // [START v2CheckPhoneNumber] // [START v2beforeSmsSentFunctionTrigger] + +const intlPrefixNumber = defineString("INTERNATIONAL_PREFIX_NUMBER", { + default: "+1", + description: "The country code that we restrict sending too.", +}); // Block SMS sending with any non-US phone number. -exports.checkphonenumber = beforeSmsSent((event) => { +exports.checkPhoneNumber = beforeSmsSent((event) => { // [END v2beforeSmsSentFunctionTrigger] // [START v2readSmsUser] // Phone number passed from the CloudEvent. @@ -103,8 +111,13 @@ exports.checkphonenumber = beforeSmsSent((event) => { // [END v2readSmsUser] // [START v2smsHttpsError] + if (!phoneNumber) { + // Throw an HttpsError so that Firebase Auth rejects the SMS sending. + throw new HttpsError("invalid-argument", "No phone number was found in the CloudEvent"); + } + // Only users of a specific region can receive SMS. - if (!phoneNumber?.startsWith("+1")) { + if (!phoneNumber.startsWith(intlPrefixNumber.value())) { // Throw an HttpsError so that Firebase Auth rejects the SMS sending. throw new HttpsError("invalid-argument", "Unauthorized phone number"); } From 4ffecf370bdf4f43db33943f5a7cc25770bc5f45 Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Fri, 3 Apr 2026 13:07:16 -0500 Subject: [PATCH 3/5] Fix lint issues (lines too long, missing require) Refactor error handling to improve readability by formatting error messages across multiple lines. --- .../auth-blocking-functions/functions/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Node/quickstarts/auth-blocking-functions/functions/index.js b/Node/quickstarts/auth-blocking-functions/functions/index.js index 8e2d198c45..3d98c067a7 100644 --- a/Node/quickstarts/auth-blocking-functions/functions/index.js +++ b/Node/quickstarts/auth-blocking-functions/functions/index.js @@ -21,6 +21,7 @@ const { beforeSmsSent, HttpsError, } = require("firebase-functions/identity"); +const {defineString} = require('firebase-functions/params'); const admin = require("firebase-admin"); admin.initializeApp(); @@ -85,10 +86,13 @@ exports.checkEmailDomain = beforeEmailSent((event) => { // Only users of a specific domain can receive emails. if (!email) { // Throw an HttpsError so that Firebase Auth rejects the email sending. - throw new HttpsError("invalid-argument", "No email was found in the CloudEvent"); + throw new HttpsError("invalid-argument", + "No email was found in the CloudEvent"); } if (!email.endsWith("@acme.com")) { - throw new HttpsError("permission-denied", "Only users from the acme.com domain can authenticate"); + throw new HttpsError("permission-denied", + "Only users from the acme.com domain can " + + "authenticate"); } // [END v2emailHttpsError] }); @@ -113,9 +117,10 @@ exports.checkPhoneNumber = beforeSmsSent((event) => { // [START v2smsHttpsError] if (!phoneNumber) { // Throw an HttpsError so that Firebase Auth rejects the SMS sending. - throw new HttpsError("invalid-argument", "No phone number was found in the CloudEvent"); + throw new HttpsError("invalid-argument", + "No phone number was found in the CloudEvent"); } - + // Only users of a specific region can receive SMS. if (!phoneNumber.startsWith(intlPrefixNumber.value())) { // Throw an HttpsError so that Firebase Auth rejects the SMS sending. From 07e8906dc6da4659f77f80b0319ea4b900648b5a Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Fri, 3 Apr 2026 13:12:43 -0500 Subject: [PATCH 4/5] Fix additional lint errors --- .../auth-blocking-functions/functions/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Node/quickstarts/auth-blocking-functions/functions/index.js b/Node/quickstarts/auth-blocking-functions/functions/index.js index 3d98c067a7..b502d18a97 100644 --- a/Node/quickstarts/auth-blocking-functions/functions/index.js +++ b/Node/quickstarts/auth-blocking-functions/functions/index.js @@ -21,7 +21,7 @@ const { beforeSmsSent, HttpsError, } = require("firebase-functions/identity"); -const {defineString} = require('firebase-functions/params'); +const {defineString} = require("firebase-functions/params"); const admin = require("firebase-admin"); admin.initializeApp(); @@ -87,12 +87,12 @@ exports.checkEmailDomain = beforeEmailSent((event) => { if (!email) { // Throw an HttpsError so that Firebase Auth rejects the email sending. throw new HttpsError("invalid-argument", - "No email was found in the CloudEvent"); + "No email was found in the CloudEvent"); } if (!email.endsWith("@acme.com")) { - throw new HttpsError("permission-denied", - "Only users from the acme.com domain can " + - "authenticate"); + throw new HttpsError("permission-denied", + "Only users from the acme.com domain can " + + "authenticate"); } // [END v2emailHttpsError] }); @@ -118,7 +118,7 @@ exports.checkPhoneNumber = beforeSmsSent((event) => { if (!phoneNumber) { // Throw an HttpsError so that Firebase Auth rejects the SMS sending. throw new HttpsError("invalid-argument", - "No phone number was found in the CloudEvent"); + "No phone number was found in the CloudEvent"); } // Only users of a specific region can receive SMS. From fcc48b4a4e58ea18282b8abf9619e34a947f3457 Mon Sep 17 00:00:00 2001 From: Jeff <3759507+jhuleatt@users.noreply.github.com> Date: Mon, 6 Apr 2026 08:53:35 -0400 Subject: [PATCH 5/5] fix typo --- Node/quickstarts/auth-blocking-functions/functions/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Node/quickstarts/auth-blocking-functions/functions/index.js b/Node/quickstarts/auth-blocking-functions/functions/index.js index b502d18a97..0d0660e95b 100644 --- a/Node/quickstarts/auth-blocking-functions/functions/index.js +++ b/Node/quickstarts/auth-blocking-functions/functions/index.js @@ -103,7 +103,7 @@ exports.checkEmailDomain = beforeEmailSent((event) => { const intlPrefixNumber = defineString("INTERNATIONAL_PREFIX_NUMBER", { default: "+1", - description: "The country code that we restrict sending too.", + description: "The country code that we restrict sending to.", }); // Block SMS sending with any non-US phone number. exports.checkPhoneNumber = beforeSmsSent((event) => {