# Use App Check to secure Navigation SDK for iOS


[Firebase App Check](https://firebase.google.com/docs/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 [App Attest](https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_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](https://developers.google.com/maps/documentation/navigation/ios-sdk/app-check.md.txt#disruption-reporting).
**Important:** App Check does not block unauthorized traffic by default. You must manually enable enforcement after verifying your app metrics (see [Step 6: Monitor your app requests and decide on enforcement](https://developers.google.com/maps/documentation/navigation/ios-sdk/app-check.md.txt#step-6-monitor-your-app-requests-and-decide-on-enforcement)).

## Why use App Check?

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

### Navigation

App Check helps block main Navigation SDK for iOS 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 iOS 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 iOS from running on untrustworthy devices, such as rooted or jailbroken phones. To support these devices, deploy a [custom attestation provider](https://firebase.google.com/docs/app-check/custom-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 providers we recommend, DeviceCheck or App Attest, are subject to [quotas and limitations set by Apple](https://developer.apple.com/documentation/DeviceCheck/preparing-to-use-the-app-attest-service#Onboard-users-gradually).
- **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](https://firebase.google.com/docs/app-check).

## Integrate your app with App Check

### Prerequisites and requirements

- An app with the Navigation SDK for iOS version 11.0 or later installed.
- The [app's bundle ID](https://developer.apple.com/documentation/appstoreconnectapi/bundle-ids).
- Your Team ID from the Membership tab in your Apple Developer console.
- If you plan to use DeviceCheck, your [private key file](https://developer.apple.com/help/account/configure-app-capabilities/create-a-devicecheck-private-key/) and [key ID](https://developer.apple.com/account/resources).
- 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](https://firebase.google.com/docs/ios/setup) to add Firebase to your app. Add your `GoogleService-Info.plist` file, unmodified, to the root level of your project.

In your `AppDelegate` file, import the following modules:

### Swift

```swift
import FirebaseCore
import FirebaseAppCheck
import GoogleNavigation
```

### Objective-C

```objective-c
@import FirebaseCore;
@import FirebaseAppCheck;
@import GoogleNavigation;
```

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

Firebase provides instructions for each default attestation provider. These instructions show you how to set up a Firebase project and add the App Check library to your app. Follow the code samples provided to initialize App Check.

1. Follow the Firebase instructions to add the App Check library:
   - [App Attest instructions](https://firebase.google.com/docs/app-check/ios/app-attest-provider#install-sdk).
   - [DeviceCheck instructions](https://firebase.google.com/docs/app-check/ios/devicecheck-provider).
2. Initialize App Check in your `AppDelegate`:
   - If you are using App Attest, create an implementation of `AppCheckProviderFactory` and register it before calling `FirebaseApp.configure()`:

     ### Swift

     ```swift
     class YourAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
         func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
             return AppAttestProvider(app: app)
         }
     }
     // In application(_:didFinishLaunchingWithOptions:)
     let providerFactory = YourAppCheckProviderFactory()
     AppCheck.setAppCheckProviderFactory(providerFactory)
     FirebaseApp.configure()
     ```

     ### Objective-C

     ```objective-c
     #import <FirebaseCore/FirebaseCore.h>
     #import <FirebaseAppCheck/FirebaseAppCheck.h>

     @interface YourAppCheckProviderFactory : NSObject <FIRAppCheckProviderFactory>
     @end

     @implementation YourAppCheckProviderFactory
     - (nullable id<FIRAppCheckProvider>)createProviderWithApp:(FIRApp *)app {
         return [[FIRAppAttestProvider alloc] initWithApp:app];
     }
     @end

     // In application:didFinishLaunchingWithOptions:
     YourAppCheckProviderFactory *providerFactory = [[YourAppCheckProviderFactory alloc] init];
     [FIRAppCheck setAppCheckProviderFactory:providerFactory];
     [FIRApp configure];
     ```
   - If you are using DeviceCheck instead, set the factory using the following:

     ### Swift

     ```swift
     AppCheck.setAppCheckProviderFactory(DeviceCheckProviderFactory())
     ```

     ### Objective-C

     ```objective-c
     FIRDeviceCheckProviderFactory *providerFactory = [[FIRDeviceCheckProviderFactory alloc] init];
     [FIRAppCheck setAppCheckProviderFactory:providerFactory];
     ```

### Step 3: Add the token provider

> [!NOTE]
> **Note:** If your app also uses other Google Maps Platform SDKs that support App Check (such as the Places SDK), you can use the same Firebase App Check configuration, but you must implement and register the token provider interface specific to each SDK.

Create a file called `AppCheckTokenProvider` (or, if you are using Objective-C, two files called `AppCheckTokenProvider.h` and `AppCheckTokenProvider.m`) at the root level of your app.

This class must conform to the `GMSAppCheckTokenProvider` protocol and implement the method `fetchAppCheckTokenWithCompletion`.

### Swift

```swift
import Foundation
import FirebaseAppCheck
import GoogleNavigation

class AppCheckTokenProvider: NSObject, GMSAppCheckTokenProvider {
    func fetchAppCheckToken(completion: @escaping (String?, Error?) -> Void) {
        AppCheck.appCheck().token(forcingRefresh: false) { token, error in
            if let error = error {
                print("App Check Error: \(error)")
                completion(nil, error)
                return
            }
            guard let token = token else {
                completion(nil, NSError(domain: "AppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Token is nil"]))
                return
            }
            print("App Check Token: \(token.token)")
            completion(token.token, nil)
        }
    }
}
```

### Objective-C

```objective-c
// AppCheckTokenProvider.h
#import <Foundation/Foundation.h>
#import <GoogleNavigation/GoogleNavigation.h>

NS_ASSUME_NONNULL_BEGIN

@interface AppCheckTokenProvider : NSObject <GMSAppCheckTokenProvider>
@end

NS_ASSUME_NONNULL_END
```

```objective-c
// AppCheckTokenProvider.m
#import "AppCheckTokenProvider.h"
#import <FirebaseAppCheck/FirebaseAppCheck.h>

@implementation AppCheckTokenProvider
- (void)fetchAppCheckTokenWithCompletion:(void (^)(NSString * _Nullable token, NSError * _Nullable error))completion {
    [[FIRAppCheck appCheck] tokenForcingRefresh:NO
                                     completion:^(FIRAppCheckToken * _Nullable token, NSError * _Nullable error) {
        if (token) {
            completion(token.token, nil);
        } else {
            completion(nil, error);
        }
    }];
}
@end
```

### Step 4: Initialize the Navigation and App Check APIs

Initialize Navigation SDK for iOS and register your token provider instance on `GMSServices`:

### Swift

```swift
// In application(_:didFinishLaunchingWithOptions:)
GMSServices.provideAPIKey("YOUR_API_KEY")

// Register your App Check token provider before initializing Navigation SDK for iOS
GMSServices.appCheckTokenProvider = AppCheckTokenProvider()
```

### Objective-C

```objective-c
// In application:didFinishLaunchingWithOptions:
[GMSServices provideAPIKey:@"YOUR_API_KEY"];

// Register your App Check token provider before initializing Navigation SDK for iOS
GMSServices.appCheckTokenProvider = [[AppCheckTokenProvider alloc] init];
```

### Step 5: Enable debugging (optional)

After App Check is enforced for Navigation SDK for iOS, your app's features that depend on Navigation SDK for iOS 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. Configure the debug provider factory in your `AppDelegate`:

   ### Swift

   ```swift
   #if targetEnvironment(simulator)
   let providerFactory = AppCheckDebugProviderFactory()
   #else
   let providerFactory = YourAppCheckProviderFactory()
   #endif
   AppCheck.setAppCheckProviderFactory(providerFactory)
   ```

   ### Objective-C

   ```objective-c
   #if TARGET_OS_SIMULATOR
   id<FIRAppCheckProviderFactory> providerFactory = [[FIRAppCheckDebugProviderFactory alloc] init];
   #else
   id<FIRAppCheckProviderFactory> providerFactory = [[YourAppCheckProviderFactory alloc] init];
   #endif
   [FIRAppCheck setAppCheckProviderFactory:providerFactory];
   ```
2. Enable logging on your Xcode project, launch the app, and locate the local debug token in the console log.
3. Copy and add this debug token to the Firebase Console. For more details, consult the [Firebase App Check debug provider documentation](https://firebase.google.com/docs/app-check/ios/debug-provider#simulator).

### Step 6: Monitor your app requests and decide on enforcement

> [!NOTE]
> **Note:** Enforcement is not strictly required for real-time disruption reports to benefit from device integrity verification; however, full protection against billing fraud, spoofing, and quota abuse relies on enabling enforcement at the project level.

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.