Image by Arek Socha from Pixabay

Security

Firebase App Check: A New Dimension in App Security

Hiranya Jayathilaka
Firebase Developers
6 min readAug 7, 2021

--

Firebase recently introduced App Check, a security feature that protects backend resources from abuse. It is a way to ensure that the requests to your app’s backend resources (e.g. Realtime Database or Cloud Storage) originate from your authentic app, and not from some unknown or malicious source.

Why App Check?

With public BaaS providers like Firebase, it is possible for an attacker to obtain the public credentials of an app, and access certain backend resources of the app. Your users and their data are typically protected from such attacks as long as you have correctly implemented user authentication, and Firebase security rules for your app. But that alone does not prevent an attacker from spamming the backend resources with spurious requests in an attempt to hog your backend resources, or incur unwarranted billing costs for you.

App Check is designed to protect the app developer

This is the problem App Check aims to solve. While Firebase Authentication and security rules protect app users by providing user authentication, App Check is designed to protect the app developer by providing app authentication.

How does it work?

An App Check enabled app first interacts with a platform-specific attestation provider to obtain an attestation of the app’s authenticity. Firebase currently supports the following attestation providers out of the box:

Once an attestation has been obtained, the app sends it to the Firebase App Check service, which further verifies the attestation against some app-specific parameters configured by the developer. If the attestation is recognized as authentic, the App Check service will issue a special App Check token for the app. The Firebase SDKs cache this token, and attach it to every backend request made by the app. Then you can activate App Check access control enforcement in the Firebase backend services like Realtime Database, Firebase Storage and Callable Functions so that they will only accept requests with valid App Check tokens attached to them.

This sounds like a handful, but as a developer you don’t really have to do much to start using Firebase App Check. A lot of the heavy lifting is handled by the Firebase SDKs, and the backend services. In most cases all you have to do is configure a few things in the Firebase console, and add a bit of new code to your app. Listing 1 shows all the extra code you have to write to add App Check support with reCAPTCHA v3 to a web app.

Listing 1: Enabling Firebase App Check with reCAPTCHA v3 in a web application

You also have the option to enable App Check in you app without activating App Check access control enforcement in the Firebase backend services (i.e. backend services will continue to accept all requests as usual). This is useful since App Check access control enforcement has the potential to break older versions of your app. The Firebase console provides detailed metrics about the sources of your backend traffic: it shows you how many requests came from authentic clients, and how many came from outdated, unknown or potentially malicious clients. You can choose to activate access control enforcement based on this information. In most cases you would at least want to wait until a large majority of your users have upgraded to the latest App Check enabled version of your app before starting enforcement.

Note that the level of security provided by App Check depends on the attestation provider. Providers like reCAPTCHA v3 can only attest that a given request came from an authentic instance of your app. But providers like App Attest and SafetyNet can go further, and also attest to whether a given request originated from an untampered device.

Protecting your own backend services with App Check

Firebase App Check helps protect your Realtime Database, Firebase Storage and Cloud Functions resources. However, if your app depends on any custom backend services of your own, you can protect those services with App Check too. For example, suppose you have implemented and deployed the backend service shown in listing 2 at api.myserver.com.

Listing 2: A backend service implementation with Node.js and Express

Here, callExternalService() might be an API call to a third party that you get billed for. You can call the above service from your web application as shown in listing 3.

Listing 3: Calling the backend service from a web application

Like most services accessible over the Internet, your service at api.myserver.com is also vulnerable to a wide range of phishing and billing attacks. An attacker can flood your endpoint with unnecessary traffic, which will slow your service, and incur a large bill due to all the additional invocations of callExternalService(). You can protect your service against this type of attacks with Firebase App Check. App Check can help you make sure that all incoming requests to your service are coming from your authentic web application, and nowhere else. Here’s how.

You can protect your own service against attacks with Firebase App Check

First, you need to change the client application so that it sends an App Check token along with the requests made to your backend endpoint. Listing 4 shows how to obtain an App Check token from the Firebase Web SDK, and include it in the outgoing request as a header.

Listing 4: Adding the App Check token to a request made by the client app

Here we have chosen to send the App Check token in a custom header named X-Firebase-AppCheck, but you can choose some other way to convey that information if you like. Just make sure to encrypt all communications with TLS, and don’t expose the tokens anywhere during transit.

Next, we modify the backend service implementation to validate the App Check token using the Firebase Admin SDK. Listing 5 illustrates how you can do that.

Listing 5: Verifying App Check tokens in a custom backend service

The appCheckVerification middleware gets executed before our actual business logic. This middleware extracts the App Check token from the request header, and verifies it using the Admin SDK. If the token is recognized as valid, we continue to process the request. If the token is missing or otherwise invalid, we halt processing the request, and send back a 401 Unauthorized response.

This simple mechanism can be used in any backend service that your Firebase apps depend on. The net result is that your backend service will become restricted to your authentic apps, and nobody else. App Check token verification is a rather efficient operation, and can be included in most backend request processing flows. The JWKS objects required to perform the verification are downloaded once, and cached by the Admin SDK for several hours at a time. Therefore after the initial cold start of the SDK, the App Check token verification can proceed entirely as a local operation without making any additional RPCs.

Why does this look familiar?

If you have used Firebase Auth in the past, and have implemented backend services that require ID token verification, you will see some parallels here. Conceptually, ID token verification and App Check token verification are quite similar. But they serve very different purposes.

Firebase Auth ID token verification is a way to establish user identity, and restrict a service to a specific group of authenticated users. App Check token verification is a way to establish app identity, and restrict a service to a specific set of apps. Depending on your use case you may need either one or both in your backend services. Here are some example use cases:

  • Only the users with the moderator role should be able to access my service. I don’t care which apps they use to interact with my service: This is a case for user authentication.
  • Only the users on my XYZ app should be able to access my service. I don’t care what roles and permissions they have on the app: This is a case for app authentication.
  • Only the users with the moderator role coming from my XYZ app should be able to access my service. Non-moderators on XYZ, and moderators logged into apps other than XYZ are not allowed: You need both user and app authentication here.

Conclusion

In other words, App Check is not a replacement for user authentication and security rules. Rather, it is a new dimension of application security that complements the already existing Firebase security tools and practices. As the threat of cyber attacks continues to intensify, developers should be more vigilant than ever, and implement security mechanisms that protect both the app users, and the backend resources that are critical for the continued operation of the apps.

--

--

Hiranya Jayathilaka
Firebase Developers

Software engineer at Shortwave. Ex-Googler. PhD in CS. Enjoys working on cloud, mobile and programming languages. Fan of all things tech and open source.