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 to block, monitor, or allow requests without valid attestation. This guide focuses on two capabilities: enforcement mode configuration and service-specific policy application.

App Check enforcement requires the App Check API enabled and applies to Firebase services like Storage, Firestore, Realtime Database, and Authentication. The examples are intentionally small. Combine them with your own App Check attestation providers and client-side integration.

Enforce App Check validation for a service

Production applications often require strict enforcement to block requests that lack 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”, Firebase Storage rejects requests without valid App Check tokens. The serviceId property targets a specific Firebase service; each service gets its own enforcement configuration. The dependsOn ensures the App Check API is enabled before creating the policy.

Monitor without blocking unauthenticated requests

Teams rolling out App Check gradually often start with monitoring mode to observe traffic patterns before enforcing validation.

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}

Setting enforcementMode to “UNENFORCED” logs App Check metrics without rejecting requests. This lets you identify legitimate clients and measure adoption before switching to ENFORCED mode. The serviceId targets Authentication, showing that each Firebase service can have independent enforcement policies.

Disable App Check enforcement entirely

Development environments or services that don’t require protection can disable enforcement to simplify testing.

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 uses the service default, typically OFF. This configuration disables App Check for Firestore, allowing all requests regardless of attestation. Use this for development or services that don’t need protection.

Beyond these examples

These snippets focus on specific App Check enforcement features: enforcement mode configuration and service-specific App Check policies. They’re intentionally minimal rather than full App Check deployments.

The examples assume pre-existing infrastructure such as a Firebase project with App Check API enabled, and target services like Storage, Firestore, Realtime Database, or Authentication. They focus on configuring enforcement policies rather than provisioning the underlying services.

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

  • App attestation provider configuration (DeviceCheck, SafetyNet, reCAPTCHA)
  • Custom enforcement rules or conditional logic
  • Replay protection settings
  • Token TTL configuration

These omissions are intentional: the goal is to illustrate how enforcement modes are wired, 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

Setup & Prerequisites
Do I need to enable the App Check API before creating a service config?
Yes, you must enable firebaseappcheck.googleapis.com first. All examples show a dependsOn relationship with gcp.projects.Service that enables this API.
Service Configuration
What Firebase services can I configure with App Check?
Four services are supported: Cloud Storage for Firebase (firebasestorage.googleapis.com), Firebase Realtime Database (firebasedatabase.googleapis.com), Cloud Firestore (firestore.googleapis.com), and Authentication (identitytoolkit.googleapis.com).
What enforcement modes are available?
You can set enforcementMode to ENFORCED or UNENFORCED, or omit it entirely for default behavior. The examples demonstrate all three configurations.
Limitations & Immutability
Can I change the service or project after creating the config?
No, both serviceId and project are immutable. Changing either requires recreating the resource.

Using a different cloud?

Explore security guides for other cloud providers: