Configure GCP Firebase App Check Service

The gcp:firebase/appCheckServiceConfig:AppCheckServiceConfig resource, part of the Pulumi GCP provider, controls App Check enforcement for individual Firebase services: whether requests require valid attestation tokens and whether metrics are collected. This guide focuses on two capabilities: enforcement mode configuration and service-specific protection settings.

App Check enforcement requires the App Check API enabled in your Firebase project. When enforcement is active, client apps must have App Check providers configured. The examples are intentionally small. Combine them with your App Check provider setup and client integration.

Enforce App Check validation for production services

Production Firebase services often require App Check enforcement to block requests without valid attestation tokens.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const appcheck = new gcp.projects.Service("appcheck", {
    project: "my-project-name",
    service: "firebaseappcheck.googleapis.com",
});
const _default = new gcp.firebase.AppCheckServiceConfig("default", {
    project: "my-project-name",
    serviceId: "firebasestorage.googleapis.com",
    enforcementMode: "ENFORCED",
}, {
    dependsOn: [appcheck],
});
import pulumi
import pulumi_gcp as gcp

appcheck = gcp.projects.Service("appcheck",
    project="my-project-name",
    service="firebaseappcheck.googleapis.com")
default = gcp.firebase.AppCheckServiceConfig("default",
    project="my-project-name",
    service_id="firebasestorage.googleapis.com",
    enforcement_mode="ENFORCED",
    opts = pulumi.ResourceOptions(depends_on=[appcheck]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		appcheck, err := projects.NewService(ctx, "appcheck", &projects.ServiceArgs{
			Project: pulumi.String("my-project-name"),
			Service: pulumi.String("firebaseappcheck.googleapis.com"),
		})
		if err != nil {
			return err
		}
		_, err = firebase.NewAppCheckServiceConfig(ctx, "default", &firebase.AppCheckServiceConfigArgs{
			Project:         pulumi.String("my-project-name"),
			ServiceId:       pulumi.String("firebasestorage.googleapis.com"),
			EnforcementMode: pulumi.String("ENFORCED"),
		}, pulumi.DependsOn([]pulumi.Resource{
			appcheck,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var appcheck = new Gcp.Projects.Service("appcheck", new()
    {
        Project = "my-project-name",
        ServiceName = "firebaseappcheck.googleapis.com",
    });

    var @default = new Gcp.Firebase.AppCheckServiceConfig("default", new()
    {
        Project = "my-project-name",
        ServiceId = "firebasestorage.googleapis.com",
        EnforcementMode = "ENFORCED",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            appcheck,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.Service;
import com.pulumi.gcp.projects.ServiceArgs;
import com.pulumi.gcp.firebase.AppCheckServiceConfig;
import com.pulumi.gcp.firebase.AppCheckServiceConfigArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var appcheck = new Service("appcheck", ServiceArgs.builder()
            .project("my-project-name")
            .service("firebaseappcheck.googleapis.com")
            .build());

        var default_ = new AppCheckServiceConfig("default", AppCheckServiceConfigArgs.builder()
            .project("my-project-name")
            .serviceId("firebasestorage.googleapis.com")
            .enforcementMode("ENFORCED")
            .build(), CustomResourceOptions.builder()
                .dependsOn(appcheck)
                .build());

    }
}
resources:
  appcheck:
    type: gcp:projects:Service
    properties:
      project: my-project-name
      service: firebaseappcheck.googleapis.com
  default:
    type: gcp:firebase:AppCheckServiceConfig
    properties:
      project: my-project-name
      serviceId: firebasestorage.googleapis.com
      enforcementMode: ENFORCED
    options:
      dependsOn:
        - ${appcheck}

When enforcementMode is set to ENFORCED, the service rejects requests that lack valid App Check tokens, with limited exceptions for privileged service accounts. The serviceId specifies which Firebase backend to protect; supported services include Cloud Storage, Realtime Database, Firestore, and Authentication. Metrics continue to be collected to help you monitor token validation and detect integration issues.

Collect metrics without blocking requests

Before enforcing App Check, teams often collect metrics to understand traffic patterns and identify clients needing updates.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const appcheck = new gcp.projects.Service("appcheck", {
    project: "my-project-name",
    service: "firebaseappcheck.googleapis.com",
});
const _default = new gcp.firebase.AppCheckServiceConfig("default", {
    project: "my-project-name",
    serviceId: "identitytoolkit.googleapis.com",
    enforcementMode: "UNENFORCED",
}, {
    dependsOn: [appcheck],
});
import pulumi
import pulumi_gcp as gcp

appcheck = gcp.projects.Service("appcheck",
    project="my-project-name",
    service="firebaseappcheck.googleapis.com")
default = gcp.firebase.AppCheckServiceConfig("default",
    project="my-project-name",
    service_id="identitytoolkit.googleapis.com",
    enforcement_mode="UNENFORCED",
    opts = pulumi.ResourceOptions(depends_on=[appcheck]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		appcheck, err := projects.NewService(ctx, "appcheck", &projects.ServiceArgs{
			Project: pulumi.String("my-project-name"),
			Service: pulumi.String("firebaseappcheck.googleapis.com"),
		})
		if err != nil {
			return err
		}
		_, err = firebase.NewAppCheckServiceConfig(ctx, "default", &firebase.AppCheckServiceConfigArgs{
			Project:         pulumi.String("my-project-name"),
			ServiceId:       pulumi.String("identitytoolkit.googleapis.com"),
			EnforcementMode: pulumi.String("UNENFORCED"),
		}, pulumi.DependsOn([]pulumi.Resource{
			appcheck,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var appcheck = new Gcp.Projects.Service("appcheck", new()
    {
        Project = "my-project-name",
        ServiceName = "firebaseappcheck.googleapis.com",
    });

    var @default = new Gcp.Firebase.AppCheckServiceConfig("default", new()
    {
        Project = "my-project-name",
        ServiceId = "identitytoolkit.googleapis.com",
        EnforcementMode = "UNENFORCED",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            appcheck,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.Service;
import com.pulumi.gcp.projects.ServiceArgs;
import com.pulumi.gcp.firebase.AppCheckServiceConfig;
import com.pulumi.gcp.firebase.AppCheckServiceConfigArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var appcheck = new Service("appcheck", ServiceArgs.builder()
            .project("my-project-name")
            .service("firebaseappcheck.googleapis.com")
            .build());

        var default_ = new AppCheckServiceConfig("default", AppCheckServiceConfigArgs.builder()
            .project("my-project-name")
            .serviceId("identitytoolkit.googleapis.com")
            .enforcementMode("UNENFORCED")
            .build(), CustomResourceOptions.builder()
                .dependsOn(appcheck)
                .build());

    }
}
resources:
  appcheck:
    type: gcp:projects:Service
    properties:
      project: my-project-name
      service: firebaseappcheck.googleapis.com
  default:
    type: gcp:firebase:AppCheckServiceConfig
    properties:
      project: my-project-name
      serviceId: identitytoolkit.googleapis.com
      enforcementMode: UNENFORCED
    options:
      dependsOn:
        - ${appcheck}

The UNENFORCED mode collects App Check metrics without rejecting requests. This lets you monitor which clients present valid tokens and plan your enforcement rollout. Other protections like user authorization remain active. Use this mode to verify your App Check integration works correctly before switching to ENFORCED.

Disable enforcement and metrics collection

Services that don’t require App Check protection can explicitly disable enforcement and metrics.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const appcheck = new gcp.projects.Service("appcheck", {
    project: "my-project-name",
    service: "firebaseappcheck.googleapis.com",
});
const _default = new gcp.firebase.AppCheckServiceConfig("default", {
    project: "my-project-name",
    serviceId: "firestore.googleapis.com",
}, {
    dependsOn: [appcheck],
});
import pulumi
import pulumi_gcp as gcp

appcheck = gcp.projects.Service("appcheck",
    project="my-project-name",
    service="firebaseappcheck.googleapis.com")
default = gcp.firebase.AppCheckServiceConfig("default",
    project="my-project-name",
    service_id="firestore.googleapis.com",
    opts = pulumi.ResourceOptions(depends_on=[appcheck]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		appcheck, err := projects.NewService(ctx, "appcheck", &projects.ServiceArgs{
			Project: pulumi.String("my-project-name"),
			Service: pulumi.String("firebaseappcheck.googleapis.com"),
		})
		if err != nil {
			return err
		}
		_, err = firebase.NewAppCheckServiceConfig(ctx, "default", &firebase.AppCheckServiceConfigArgs{
			Project:   pulumi.String("my-project-name"),
			ServiceId: pulumi.String("firestore.googleapis.com"),
		}, pulumi.DependsOn([]pulumi.Resource{
			appcheck,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var appcheck = new Gcp.Projects.Service("appcheck", new()
    {
        Project = "my-project-name",
        ServiceName = "firebaseappcheck.googleapis.com",
    });

    var @default = new Gcp.Firebase.AppCheckServiceConfig("default", new()
    {
        Project = "my-project-name",
        ServiceId = "firestore.googleapis.com",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            appcheck,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.Service;
import com.pulumi.gcp.projects.ServiceArgs;
import com.pulumi.gcp.firebase.AppCheckServiceConfig;
import com.pulumi.gcp.firebase.AppCheckServiceConfigArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var appcheck = new Service("appcheck", ServiceArgs.builder()
            .project("my-project-name")
            .service("firebaseappcheck.googleapis.com")
            .build());

        var default_ = new AppCheckServiceConfig("default", AppCheckServiceConfigArgs.builder()
            .project("my-project-name")
            .serviceId("firestore.googleapis.com")
            .build(), CustomResourceOptions.builder()
                .dependsOn(appcheck)
                .build());

    }
}
resources:
  appcheck:
    type: gcp:projects:Service
    properties:
      project: my-project-name
      service: firebaseappcheck.googleapis.com
  default:
    type: gcp:firebase:AppCheckServiceConfig
    properties:
      project: my-project-name
      serviceId: firestore.googleapis.com
    options:
      dependsOn:
        - ${appcheck}

Omitting the enforcementMode property (or deleting the resource entirely) returns the service to its default unconfigured state. In this mode, App Check is not enforced and metrics are not collected, though other protections like user authorization remain active. This is equivalent to the OFF state in the REST API.

Beyond these examples

These snippets focus on specific service configuration features: enforcement modes and service-specific protection settings. They’re intentionally minimal rather than complete App Check deployments.

The examples assume pre-existing infrastructure such as a Firebase project with App Check API enabled, and client apps configured with App Check providers when enforcement is active. They focus on configuring enforcement rather than provisioning the underlying App Check providers.

To keep things focused, common App Check patterns are omitted, including:

  • App Check provider configuration (DeviceCheck, Play Integrity, reCAPTCHA)
  • Custom token generation and validation
  • Replay protection settings
  • Service-specific exceptions and allowlists

These omissions are intentional: the goal is to illustrate how enforcement modes are configured, not provide drop-in App Check modules. See the Firebase AppCheckServiceConfig resource reference for all available configuration options.

Let's configure GCP Firebase App Check Service

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Enforcement Modes & Behavior
What happens if I enforce App Check before my users update their apps?
Users with outdated apps will lose access to your Firebase services. Use UNENFORCED mode first to collect metrics and verify client compatibility before switching to ENFORCED. For apps that haven’t launched yet, you can enable ENFORCED immediately since there are no outdated clients.
What are the App Check enforcement modes?

There are three modes:

  1. Unset (OFF) - No enforcement or metrics collection (default for unconfigured services)
  2. UNENFORCED - Metrics collected but requests not blocked; helps you decide when to enforce
  3. ENFORCED - Requests without valid App Check tokens are rejected (with some exceptions for privileged service accounts)
What protections remain active when App Check is not enforced?
Other applicable protections like user authorization continue to be enforced regardless of App Check mode. App Check is an additional layer of protection, not a replacement for existing security measures.
What happens when I delete this resource?
Deleting the resource switches enforcement to OFF, which stops both enforcement and metrics collection. To keep collecting metrics while disabling enforcement, set enforcementMode to UNENFORCED instead of deleting the resource.
Service Configuration
Which Firebase services support App Check enforcement?

Currently, four services are supported:

  • firebasestorage.googleapis.com (Cloud Storage for Firebase)
  • firebasedatabase.googleapis.com (Firebase Realtime Database)
  • firestore.googleapis.com (Cloud Firestore)
  • identitytoolkit.googleapis.com (Authentication)
Why do I need to enable the App Check API before creating this resource?
The firebaseappcheck.googleapis.com service must be enabled in your project before you can configure enforcement for individual Firebase services. All examples show this dependency using dependsOn.
Resource Lifecycle
Can I change the service or project after creating the resource?
No, both serviceId and project are immutable. Changing either property will force resource replacement.
How do I import an existing App Check service configuration?
You can import using three formats: projects/{{project}}/services/{{service_id}}, {{project}}/{{service_id}}, or just {{service_id}}. The service ID must be one of the four supported Firebase services.

Using a different cloud?

Explore security guides for other cloud providers: