You can trigger functions in response to the creation and deletion of Firebase Authentication user accounts. For example, you could send a welcome email to a user who has just created an account in your app. Examples on this page are based on a sample that does exactly this—sends welcome and farewell emails upon account creation and deletion.
For more examples of use cases, see What can I do with Cloud Functions?.
Trigger a function on user creation
You can create a function that triggers when an Authentication user is created using
the
onUserCreated
event handler from the firebase-functions/v2/identity subpackage:
const { onUserCreated } = require("firebase-functions/identity"); const { defineSecret } = require("firebase-functions/params"); const { logger } = require("firebase-functions"); const { sendWelcomeEmail } = require("./utils/myEmailService"); const emailApiKey = defineSecret("EMAIL_API_KEY"); exports.newUserWelcome = onUserCreated( { secrets: [emailApiKey] }, async (event) => { const { uid, email, displayName } = event.data; if (!email) { logger.log(`User ${uid} does not have an email address.`); return; } await sendWelcomeEmail(email, displayName); }, );
Authentication accounts will trigger user creation events for Cloud Functions when:
- A user creates an email account and password.
- A user signs in for the first time using a federated identity provider.
- The developer creates an account using the Admin SDK.
- A user signs in to a new anonymous auth session for the first time.
A Cloud Functions event is not triggered when a user signs in for the first time using a custom token.
Configure trigger options and multi-tenancy
You can configure your function by passing an options object (AuthOptions) as
the first parameter to onUserCreated:
/** * Sends a welcome email scoped to a specific tenant in Identity Platform. */ exports.sendWelcomeEmailToTenant = onUserCreated( { secrets: [emailApiKey], // Only trigger when a user is a member of this tenant tenantId: "my-tenant-id", }, async (event) => { const { uid, email, displayName } = event.data; // Customize the email for this tenant await sendWelcomeEmail(email, displayName, event.tenantId); }, ); /** * Sends a welcome email only to users not associated with any tenant. */ exports.sendWelcomeEmailNoTenant = onUserCreated( { secrets: [emailApiKey], // Only trigger when a user is NOT a member of a tenant tenantId: IS_NOT_TENANT, }, async (event) => { const { email, displayName } = event.data; // Send a generic welcome email await sendWelcomeEmail(email, displayName); }, );
If your project uses Identity Platform multi-tenancy, you can scope the trigger:
- Default project (no tenant): Set
tenantIdtoIS_NOT_TENANTto listen only for users created in the default project. - Specific tenant: Provide the string ID of the tenant (for example,
{ tenantId: "tenant-id-1" }) to listen only for users created in that tenant. - All tenants and users: If
tenantIdis omitted, the function triggers on user creation events across all tenants and default project users in the project.
In addition to tenantId, you can specify standard 2nd gen configuration
options including region, concurrency, cpu, memory, timeoutSeconds,
minInstances, maxInstances, and secrets.
Access user attributes
From the user data returned to your function, you can access the list of user
attributes available in the newly created user's
UserRecord
object via event.data. For example, you can get the user's email and display
name as shown:
const { uid, email, displayName } = event.data;
Authentication triggers in 2nd gen receive an
AuthEvent
object. In addition to event.data, you can access event metadata such as:
event.id: A unique identifier for the event.event.type: The event type (google.firebase.auth.user.v2.created).event.time: An ISO 8601 timestamp representing when the event occurred.event.project: The Google Cloud project ID.event.tenantId: The Identity Platform tenant ID associated with the user, if applicable.
Trigger a function on user deletion
Just as you can trigger a function on user creation, you can respond to user
deletion events. Use the
onUserDeleted
event handler from firebase-functions/v2/identity as shown:
const { onUserDeleted } = require("firebase-functions/identity"); const { defineSecret } = require("firebase-functions/params"); const { logger } = require("firebase-functions"); const { sendGoodbyeEmail } = require("./utils/myEmailService"); const emailApiKey = defineSecret("EMAIL_API_KEY"); exports.deletedUserFarewell = onUserDeleted( { secrets: [emailApiKey] }, async (event) => { const { uid, email, displayName } = event.data; if (!email) { logger.log(`User ${uid} does not have an email address.`); return; } await sendGoodbyeEmail(email, displayName); }, );
As with onUserCreated, you can configure onUserDeleted with options like
{ tenantId: IS_NOT_TENANT } to restrict triggers to users in the default
project.
Trigger blocking functions
If you've upgraded to Firebase Authentication with Identity Platform, you can extend Firebase Authentication using blocking functions.
Blocking functions let you execute custom code synchronously that modifies the result of a user registering or signing in to your app. Unlike background triggers, which run asynchronously after an event has finished, blocking functions allow you to prevent a user from authenticating if they don't meet certain criteria, or update a user's information and claims before returning it to your client app.
Best practices for 2nd gen triggers
When implementing 2nd gen authentication triggers, keep the following best practices in mind:
- Account for concurrency: Cloud Functions (2nd gen) instances process concurrent requests (defaulting to 80 concurrent requests when CPU ≥ 1). Ensure that your function does not rely on global mutable state between concurrent executions.
- Design for idempotency: Event delivery in 2nd gen is at-least-once via Eventarc. Ensure that your functions are idempotent; for example, verify that a welcome email has not already been sent or a database entry initialized before performing side effects.
- Scope multi-tenant functions: If your application uses Identity Platform
multi-tenancy, verify whether your functions should handle events across all
tenants or only specific ones. Use
tenantId: IS_NOT_TENANTto prevent tenant users from triggering functions intended only for the primary project. - Manage regions and resource allocation: Specify the function location
(
region) to minimize network latency between your authentication provider and your function execution environment.