Use App Check to secure Navigation SDK for Android

Firebase App Check provides protection for calls from your app to Google Maps Platform by blocking traffic that comes from sources other than your legitimate apps. It does this by requesting an evaluation of the app or device's authenticity from an attestation provider like Play Integrity. When you integrate your app with App Check, you add protection against malicious and unauthorized requests, which in turn protects your billing from unauthorized charges. App Check also significantly improves real-time disruption reporting in your fleet app ecosystem, thereby benefiting all the drivers who use your app. For more information, see Disruption reporting.

Why use App Check?

App Check protects two distinct areas of the Navigation SDK for Android: the main navigation functionality and disruption reporting.

App Check helps block main Navigation SDK for Android requests from malicious or unauthorized sources. This directly benefits you by protecting your project from billing fraud and quota exhaustion.

Disruption reporting

App Check is highly recommended if your app supports real-time disruption reporting and voting capabilities. Enabling App Check ensures your drivers are provided the most accurate routes accounting for all real-time feedback.

Why App Check matters for reporting:

  • The high trust bar for closures: Route-impacting events, such as road closures, can significantly alter routing behavior for all drivers. To protect the map from potential vandalism, spam, or inaccurate reporting, Google's moderation infrastructure for road closure disruptions relies on strong device and app integrity signals.
  • How App Check validates reports: User reports and votes sent from Navigation SDK for Android include the App Check token, which is used by Google's backend to validate the legitimacy of the feedback, raising its trust level and allowing it to be evaluated for live map impact.
  • The impact of omitting App Check: Reports submitted without a valid App Check token are evaluated under a lower-trust model and may be processed solely as silent signals. This means that while your users can still report and vote, their reports are less likely to be visible on the map or affect other drivers' routes and will require additional validation.

Is App Check right for me?

App Check is recommended in most cases; however, App Check isn't needed or isn't supported in the following scenarios:

  • Private or experimental apps: If your app isn't publicly accessible, App Check isn't needed.
  • Compromised devices: The recommended attestation providers prevent Navigation SDK for Android from running on untrustworthy devices, such as rooted or jailbroken phones. To support these devices, deploy a custom attestation provider.
  • Non-GMS Android devices: Android devices must run Google Mobile Services (GMS) for Play Integrity. If you plan to support non-GMS Android devices, deploy a custom attestation provider.

Overview of implementation steps

At a high level, you'll follow these steps to integrate your app with App Check:

  1. Add Firebase to your app.
  2. Add the App Check library and initialize App Check.
  3. Add a token provider. This step invokes the attestation provider of your choice to verify the integrity of the device or app.
  4. Initialize the Navigation and App Check APIs.
  5. Enable debugging. This is useful during development or in continuous integration (CI) environments.
  6. Monitor your app requests before enabling enforcement. This way, you seamlessly enforce App Check without disrupting your users.

Considerations when planning an App Check integration

  • Attestation Provider Quotas: The attestation provider we recommend, Play Integrity, has a daily call limit for its Standard API usage tier. For more information about call limits, see the Setup page in the Google Play Integrity developer documentation.
  • Startup Latency: In most situations, your users won't experience latency during regular use, because App Check tokens are cached on the device. The system automatically refreshes App Check tokens in the background before expiration to maintain seamless performance. However, if a valid App Check token isn't present, your app users will experience some latency on startup. For example, this latency occurs during cold starts when a cached token is expired or missing.
  • Token TTL: Time to live (TTL) determines the amount of time for which the App Check token is valid before it needs to be refreshed. You can configure this duration from 30 minutes to 7 days in the Firebase console. A duration of 1 hour is recommended as a secure baseline, but the SDK automatically attempts background refreshes at approximately half the TTL duration. For step-by-step console instructions, see the Firebase App Check documentation.

Integrate your app with App Check

Prerequisites and requirements

  • An app with the Navigation SDK for Android version 7.9 or later installed.
  • The SHA-256 certificate fingerprint of your app.
  • Your app's package name.
  • You must be the owner of the app in the Google Cloud console.
  • Your app's project ID from the Google Cloud console.

Step 1: Add Firebase to your app

Follow the instructions in the Firebase developer documentation to add Firebase to your app. Add your google-services.json file to the app level directory of your project.

Step 2: Add the App Check library and initialize App Check

Add the App Check dependency to your app's build.gradle file:

Groovy (build.gradle)

dependencies {
    // Import the Firebase BoM
    implementation platform('com.google.firebase:firebase-bom:34.17.0')
    // Add the dependency for the App Check library with Play Integrity
    implementation 'com.google.firebase:firebase-appcheck-playintegrity'
}

Initialize App Check in your Application class or main activity:

Java

import com.google.firebase.FirebaseApp;
import com.google.firebase.appcheck.FirebaseAppCheck;
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory;

// Initialize Firebase App
FirebaseApp.initializeApp(/* context= */ this);

// Initialize App Check
FirebaseAppCheck firebaseAppCheck = FirebaseAppCheck.getInstance();
firebaseAppCheck.installAppCheckProviderFactory(
    PlayIntegrityAppCheckProviderFactory.getInstance());

Kotlin

import com.google.firebase.Firebase
import com.google.firebase.appcheck.appCheck
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
import com.google.firebase.initialize

// Initialize Firebase App
Firebase.initialize(context = this)

// Initialize App Check
Firebase.appCheck.installAppCheckProviderFactory(
    PlayIntegrityAppCheckProviderFactory.getInstance(),
)

Step 3: Add the token provider

Create an implementation of the MapsAppCheckTokenProvider interface. This provider asynchronously fetches App Check tokens from Firebase App Check and passes them to the Navigation SDK for Android network stack using the MapsAppCheckTokenCallback:

Java

import com.google.android.gms.maps.MapsAppCheckTokenCallback;
import com.google.android.gms.maps.MapsAppCheckTokenProvider;
import com.google.firebase.appcheck.FirebaseAppCheck;

public class NavigationTokenProvider implements MapsAppCheckTokenProvider {
  @Override
  public void fetchToken(MapsAppCheckTokenCallback callback) {
    FirebaseAppCheck.getInstance()
        .getAppCheckToken(false) // forcingRefresh = false
        .addOnSuccessListener(
            tokenResult -> {
              String token = tokenResult.getToken();
              callback.onSuccess(token);
            })
        .addOnFailureListener(
            e -> {
              callback.onFailure();
            });
  }
}

Kotlin

import com.google.android.gms.maps.MapsAppCheckTokenCallback
import com.google.android.gms.maps.MapsAppCheckTokenProvider
import com.google.firebase.appcheck.FirebaseAppCheck

class NavigationTokenProvider : MapsAppCheckTokenProvider {
    override fun fetchToken(callback: MapsAppCheckTokenCallback) {
        FirebaseAppCheck.getInstance()
            .getAppCheckToken(false)
            .addOnSuccessListener { tokenResult ->
                callback.onSuccess(tokenResult.token)
            }
            .addOnFailureListener {
                callback.onFailure()
            }
    }
}

Step 4: Initialize the Navigation and App Check APIs

Initialize Navigation SDK for Android and register your unified token provider instance using MapsApiSettings.setAppCheckTokenProvider():

Java

import com.google.android.gms.maps.MapsApiSettings;

// Register your App Check token provider before initializing Navigation SDK for Android
MapsApiSettings.setAppCheckTokenProvider(context, new NavigationTokenProvider());

Kotlin

import com.google.android.gms.maps.MapsApiSettings

// Register your App Check token provider before initializing Navigation SDK for Android
MapsApiSettings.setAppCheckTokenProvider(context, NavigationTokenProvider())

Step 5: Enable debugging (optional)

After App Check is enforced for Navigation SDK for Android, your app's features that depend on Navigation SDK for Android won't run in a simulator or from a continuous integration (CI) environment because these environments don't qualify as valid devices. To run your app in these environments during development and testing, you need to create a debug build of your app that uses the App Check debug provider instead of a production attestation provider.

  1. Add the debug provider dependency to your app's build.gradle file:

    Groovy (build.gradle)

    dependencies {
        implementation 'com.google.firebase:firebase-appcheck-debug'
    }
  2. Configure App Check to use the debug provider factory in your debug builds:

    Java

    import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory;
    import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory;
    
    if (BuildConfig.DEBUG) {
        firebaseAppCheck.installAppCheckProviderFactory(
            DebugAppCheckProviderFactory.getInstance()
        );
    } else {
        firebaseAppCheck.installAppCheckProviderFactory(
            PlayIntegrityAppCheckProviderFactory.getInstance()
        );
    }

    Kotlin

    import com.google.firebase.Firebase
    import com.google.firebase.appcheck.appCheck
    import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
    import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
    
    if (BuildConfig.DEBUG) {
        Firebase.appCheck.installAppCheckProviderFactory(
            DebugAppCheckProviderFactory.getInstance(),
        )
    } else {
        Firebase.appCheck.installAppCheckProviderFactory(
            PlayIntegrityAppCheckProviderFactory.getInstance(),
        )
    }
  3. Launch your app on an emulator or debug device. App Check will print a local debug token to your logcat output.
  4. Copy and register this debug token in the Firebase Console. For more details, consult the Firebase App Check debug provider documentation.

Step 6: Monitor your app requests and decide on enforcement

Before enabling enforcement, monitor your app requests to make sure that you won't disrupt legitimate users.

  1. Visit the App Check metrics screen in the Firebase console to see the percentage of verified versus unverified traffic.
  2. Once you are sure that the majority of your traffic is verified and legitimate users have updated to a version of your app containing your App Check implementation, enable enforcement.
  3. Once enforcement is on, App Check will reject all traffic without a valid App Check token.