Implementa gradualmente Firebase App Check utilizzando Firebase Remote Config

1. Introduzione

Puoi utilizzare Firebase App Check con App Attest per proteggere i tuoi servizi backend e verificare che le richieste ai servizi Firebase provengano dalla tua app autentica.

In genere è consigliabile eseguire l'onboarding graduale degli utenti nel servizio di attestazione dell'app per evitare di raggiungere i limiti di quota. Per ulteriori informazioni, consulta la documentazione di Apple " Preparazione all'uso del servizio di attestazione dell'app ".

La possibilità di rilasciare gli aggiornamenti delle app in modo incrementale utilizzando la funzionalità App Store Connect di Apple, come descritto in " Rilascio di un aggiornamento di versione in fasi ", può rendere più agevole l'implementazione di App Check. Questa è una soluzione semplice e diretta. Tuttavia, il rilascio graduale dell'aggiornamento della versione di un'app non ti consente di controllare l'implementazione o modificare il comportamento delle app aggiornate esistenti senza pubblicare una nuova versione dell'app.

Un modo per avere maggiore controllo sull'implementazione di App Check con App Attest è utilizzare Firebase Remote Config per abilitare App Check con App Attest per una percentuale di utenti della tua app alla volta. Ciò può contribuire a evitare la limitazione da parte dei server di attestazione. Google Analytics può essere utilizzato per osservare l'impatto del lancio sugli utenti.

Cosa imparerai

In questo codelab in più passaggi imparerai come utilizzare Firebase Remote Config per implementare App Check per la tua app.

Questo codelab utilizza un progetto Firebase basato sull'app di avvio rapido DatabaseExample e integrato con Firebase App Check, come descritto nel codelab Firebase App Check for Apple Platforms . L'app di avvio rapido DatabaseExample consente agli utenti di accedere e aggiungere post utilizzando le funzionalità di Firebase Realtime Database.

Puoi anche adattare i passaggi di questo codelab per testare la tua app.

Prerequisiti

Di cosa avrai bisogno

  • Xcodice 12.5+
  • Per i test di attestazione dell'app:
  • Progetto Firebase con:
  • Accesso al progetto Firebase associato alla tua app, con autorizzazioni per creare e gestire Remote Config e per visualizzare Google Analytics

2. Creare un provider di attestazioni personalizzato

In questo passaggio creeremo una classe provider personalizzata per fornire un token solo quando l'attestazione dell'app è abilitata. Remote Config si basa su un'istanza dell'app Firebase configurata e il provider personalizzato implementato in questo passaggio funge da segnaposto per completare la configurazione.

Per completare i passaggi seguenti, dovrai aggiungere Firebase , FirebaseRemoteConfig e FirebaseAnalytics nella sezione Framework, librerie e contenuto incorporato della tua app in Xcode. Per un esempio di come eseguire questa operazione, fare riferimento al controllo dell'app Firebase per le piattaforme Apple codelab .

  1. Crea un file " MyAppCheckProvider " che sia una sottoclasse di NSObject conforme al protocollo AppCheckProvider .
  2. Includi un metodo getToken() vuoto che compilerai in seguito.

Consulta il seguente codice di esempio per la classe provider personalizzata con il metodo getToken() vuoto.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

Per creare un'istanza di AppAttestProvider , dovrai passare un'istanza del FirebaseApp corrispondente. Crea una proprietà memorizzata per esso e accettala come parametro inizializzatore:

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

Inoltra la richiesta del token al provider di attestazione dell'app

Ora hai tutto per inoltrare la richiesta del token al provider App Attest nel tuo metodo getToken() .

Nota: scopri di più sul metodo getToken() nel riferimento al framework FirebaseAppCheck .

Aggiungi il seguente codice al tuo metodo getToken() :

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  private lazy var appAttestProvider = AppAttestProvider(app: firebaseApp)

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
    // Fetch App Attest flag from Remote Config
    let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
    remoteConfig.fetchAndActivate { remoteConfigStatus, error in
      // Get App Attest flag value
      let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

      guard appAttestEnabled else {
        // Skip attestation if App Attest is disabled. Another attestation
        // method like DeviceCheck may be used instead of just skipping.
        handler(nil, MyProviderError.appAttestIsDisabled)
        return
      }

      // Try to obtain an App Attest provider instance and fail if cannot
      guard let appAttestProvider = self.appAttestProvider else {
        handler(nil, MyProviderError.appAttestIsUnavailable)
        return
      }

      // If App Attest is enabled for the app instance, then forward the
      // Firebase App Check token request to the App Attest provider
      appAttestProvider.getToken(completion: handler)
    }
  }
}

enum MyProviderError: Error {
  case appAttestIsDisabled
  case appAttestIsUnavailable
  case unexpected(code: Int)
}

Il codice precedente controlla un parametro booleano Remote Config AppAttestEnabled (questo parametro Remote Config verrà creato successivamente nel codelab). Se il valore è false, il codice ha esito negativo, indicando che App Check non è stato implementato nel dispositivo corrente. Se il valore è true, il codice tenta di ottenere un provider di attestazione dell'app e, se non ci riesce, fallisce. Se questi controlli degli errori vengono superati, il codice inoltrerà la richiesta del token al provider di attestazione dell'app.

Aggiungi eventi di Analytics

Aggiungendo eventi Analytics, ottieni informazioni migliori sul successo dell'implementazione di App Check. L'analisi aiuterà a determinare se l'attestazione dell'app deve essere abilitata per un pubblico più ampio.

Registra due eventi di Analytics: AppAttestSuccess in caso di successo e AppAttestFailure in caso di errore. Questi due eventi di Analytics possono aiutarti a monitorare il successo dell'implementazione di App Check e aiutarti a decidere se è opportuno procedere con un'implementazione più ampia.

func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
  // Fetch Remote Config.
  let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
  remoteConfig.fetchAndActivate { remoteConfigStatus, error in
    // Get App Attest flag value from Remote Config.
    let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

    guard appAttestEnabled else {
      // Skip attestation if App Attest is disabled. Another attestation
      // method like DeviceCheck may be used instead of just skipping.
      handler(nil, MyProviderError.appAttestIsDisabled)
      return
    }

    // Try to obtain an App Attest provider instance and fail otherwise.
    guard let appAttestProvider = self.appAttestProvider else {
      handler(nil, MyProviderError.appAttestIsUnavailable)
      return
    }

    // If App Attest is enabled for the app instance, then forward the
    // Firebase App Check token request to the App Attest provider.
    appAttestProvider.getToken { token, error in
      // Log an Analytics event to track attestation success rate.
      let appAttestEvent: String
      if (token != nil && error == nil) {
        appAttestEvent = "AppAttestSuccess"
      } else {
        appAttestEvent = "AppAttestFailure"
      }
      Analytics.logEvent(appAttestEvent, parameters: nil)

      // Pass the result to the handler
      handler(token, error)
    }
  }
}

3. Aggiorna la classe Provider Factory

Dopo aver implementato la logica per inoltrare la richiesta del token al provider App Attest e aggiunto alcuni eventi di Analytics, devi aggiornare MyAppCheckProviderFactory.class che hai creato nel codelab App Check for Apple Platforms . Questa classe prenderà di mira il provider di debug App Check per i simulatori e in caso contrario il provider personalizzato.

Modifica il codice seguente nella classe MyAppCheckProviderFactory creata nel codelab Firebase App Check per piattaforme Apple :

// MyAppCheckProviderFactory.swift

import Firebase

class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
      #if targetEnvironment(simulator)
      // App Attest is not available on simulators.
      // Use a debug provider.
      let provider = AppCheckDebugProvider(app: app)

      // Print only locally generated token to avoid a valid token leak on CI.
      print("Firebase App Check debug token: \(provider?.localDebugToken() ?? "" )")

      return provider
      #else
      if #available(iOS 14.0, *) {
        // Use your custom App Attest provider on real devices.
        return MyAppCheckProvider(app: app)
      } else {
        return DeviceCheckProvider(app: app)
      }
      #endif
  }
}

Conferma di aver impostato AppCheckProviderFactory prima di configurare FirebaseApp :

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

@main
struct DatabaseExampleApp: App {
  init() {
    AppCheck.setAppCheckProviderFactory(MyAppCheckProviderFactory())
    FirebaseApp.configure()
  }

  // ...
}

4. Aggiungi un parametro Remote Config nella console Firebase

Ora aggiungerai il parametro Remote Config AppAttestEnabled alla console Firebase. Il tuo metodo getToken richiede questo parametro.

Per creare un parametro Remote Config nella console Firebase:

  1. Apri Remote Config per il tuo progetto e fai clic su Aggiungi parametro . Se è la prima volta che utilizzi Remote Config, fai clic su Crea configurazione .
  2. Nel campo Nome parametro (chiave) immettere AppAttestEnabled .
  3. Dal menu a discesa Tipo di dati , seleziona Booleano .
  4. Dal menu a discesa Valore predefinito , seleziona false .

Creazione del parametro di configurazione remota nella console Firebase

Prima di fare clic su Salva, crea un valore condizionale per il 10% degli utenti:

  1. Fai clic su Aggiungi nuovo > Valore condizionale > Crea nuova condizione .
  2. Nel campo Nome , inserisci un nome per la condizione.
  3. In Si applica se... , seleziona Utente in percentile casuale , <= , quindi immetti 10 nel campo % .
  4. Fare clic su Crea condizione .

Definizione di una condizione di configurazione remota nella console Firebase

Imposta il valore condizionale su true in modo che App Attest venga distribuito al 10% dei tuoi utenti.

  1. Imposta il valore su true per la condizione appena creata.
  2. Fare clic su Salva .

Revisione del parametro Remote Config nella console Firebase

Al termine, pubblicare le modifiche di Remote Config.

Testa l'implementazione sul tuo dispositivo

Per testare i diversi valori del flag Remote Config sul tuo dispositivo senza modificare il codice dell'app, configura un esperimento sul parametro AppAttestEnabled seguendo il tutorial Creare esperimenti Firebase Remote Config con test A/B . La sezione tutorial " Convalida il tuo esperimento su un dispositivo di test " spiega come assegnare valori diversi al tuo dispositivo di test.

Il passaggio finale consiste nell'utilizzare Google Analytics per monitorare il successo dell'implementazione dell'attestazione dell'app.

5. Controlla il successo della tua implementazione di AppCheck

Puoi misurare il successo della tua implementazione nella dashboard Eventi di Analytics. Controlla gli eventi AppAttestSuccess e AppAttestFailure . Potrebbero essere necessarie fino a 24 ore per visualizzare gli eventi nella dashboard. In alternativa, puoi abilitare il debug e utilizzare DebugView per visualizzare gli eventi di debug più rapidamente.

Facoltativamente, puoi monitorare la dashboard di Crashlytics per verificare l'aumento della percentuale di arresti anomali. Per ulteriori informazioni sull'aggiunta di Crashlytics alla tua app, consulta Iniziare con Firebase Crashlytics .

Una volta visualizzati principalmente eventi AppAttestSuccess e pochi eventi AppAttestFailure , è un buon segno che puoi aumentare la percentuale di utenti con App Attest abilitato modificando la condizione nel parametro Remote Config AppAttestEnabled .

Revisione degli eventi di Analytics nella console Firebase

Facoltativo: sfruttare il pubblico di Google Analytics

Se desideri sfruttare ulteriormente l'evento AppAttestEnabled Analytics, puoi creare un pubblico di Analytics per monitorare gli utenti con AppAttestEnabled impostato su true.

App Attest è stato rilasciato con iOS 14.0. Alcuni dei tuoi utenti potrebbero non essere presenti in questa versione e quindi non essere idonei per l'attestazione dell'app. Puoi registrare un altro evento di Analytics per monitorare questi utenti, quindi scegliere come target quel pubblico per un altro metodo di attestazione, come DeviceCheck .

Facoltativo: utilizzare Crashlytics per monitorare gli arresti anomali

Per comprendere meglio la stabilità della tua app durante l'implementazione, utilizza Firebase Crashlytics per monitorare arresti anomali e non fatali.

6. Congratulazioni!

Hai implementato con successo App Check con Remote Config 🎉

Risorse addizionali: