Implementa la Verificación de aplicaciones de Firebase de forma gradual con Firebase Remote Config

1. Introducción

Puedes usar la Verificación de aplicaciones de Firebase con App Attest para proteger tus servicios de backend y verificar que las solicitudes a los servicios de Firebase provengan de tu app auténtica.

Por lo general, se recomienda incorporar usuarios de forma gradual en el servicio de App Attest para evitar alcanzar los límites de cuota. Si deseas obtener más información, consulta la documentación "Preparing to Use the App Attest Service" de Apple.

La capacidad de lanzar actualizaciones de la aplicación de forma incremental con la función App Store Connect de Apple, como se describe en "Lanzar una actualización de la versión en etapas", puede facilitar el lanzamiento de la Verificación de aplicaciones. Esta es una solución simple y directa. Sin embargo, lanzar la actualización de la versión de una app en etapas no te permite controlar el lanzamiento ni cambiar el comportamiento de las apps existentes y actualizadas sin publicar una nueva versión.

Una forma de tener más control sobre el lanzamiento de la Verificación de aplicaciones mediante App Attest es usar Firebase Remote Config para habilitar la Verificación de aplicaciones con App Attest para un porcentaje de los usuarios de tu aplicación a la vez. Esto puede ayudar a evitar la limitación de los servidores de certificación. Google Analytics se puede usar para observar el impacto del lanzamiento en los usuarios.

Qué aprenderás

En este codelab de varios pasos, aprenderás a usar Firebase Remote Config para lanzar la Verificación de aplicaciones en tu app.

En este codelab, se usa un proyecto de Firebase basado en la app de inicio rápido de DatabaseExample y integrado en la Verificación de aplicaciones de Firebase, como se describe en el codelab de Verificación de aplicaciones de Firebase para plataformas de Apple. La app de inicio rápido de DatabaseExample permite que los usuarios accedan y agreguen publicaciones con las funciones de Firebase Realtime Database.

También puedes adaptar los pasos de este codelab para probar tu propia app.

Requisitos previos

Requisitos

  • Xcode 12.5 o versiones posteriores
  • Para pruebas de App Attest:
    • Una cuenta de desarrollador de Apple que te permita crear nuevos identificadores de apps
    • Una aplicación con un ID de app explícito que tenga habilitada la función App Attest. Consulta los artículos Registra un ID de app y Habilita las funciones de la app si necesitas ayuda con el proceso.
    • Un dispositivo iOS o iPadOS compatible con App Attest
  • Proyecto de Firebase con:
  • Acceso al proyecto de Firebase asociado con tu app, con permisos para crear y administrar Remote Config y ver Google Analytics

2. Crea un proveedor de certificación personalizado

En este paso, crearemos una clase de proveedor personalizada para proporcionar un token solo cuando esté habilitado App Attest. Remote Config depende de una instancia de app de Firebase configurada. El proveedor personalizado que implementes en este paso actúa como el marcador de posición para finalizar la configuración.

Para completar los siguientes pasos, deberás agregar Firebase, FirebaseRemoteConfig y FirebaseAnalytics en la sección Frameworks, bibliotecas y contenido incorporado de tu app en Xcode. Si quieres ver un ejemplo de cómo hacerlo, consulta el codelab de Verificación de aplicaciones de Firebase para plataformas de Apple.

  1. Crea un archivo "MyAppCheckProvider" que sea una subclase de NSObject de acuerdo con el protocolo AppCheckProvider.
  2. Incluye un método getToken() vacío que completarás más adelante.

Consulta el siguiente código de ejemplo para la clase de proveedor personalizado con el método getToken() vacío.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

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

Para crear una instancia de AppAttestProvider, debes pasar una instancia del FirebaseApp correspondiente. Crea una propiedad almacenada para ella y acéptala como un parámetro de inicializador:

// 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) {}
}

Reenvía la solicitud de token al proveedor de App Attest

Ahora tienes todo para reenviar la solicitud de token al proveedor de App Attest en tu método getToken().

Nota: Obtén más información sobre el método getToken() en la referencia del framework de FirebaseAppCheck.

Agrega el siguiente código a tu método 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)
}

El código anterior verifica un parámetro booleano AppAttestEnabled de Remote Config (se creará este parámetro de Remote Config más adelante en el codelab). Si el valor es falso, el código fallará, lo que indica que no se lanzó la Verificación de aplicaciones en el dispositivo actual. Si el valor es verdadero, el código intenta obtener un proveedor de App Attest y falla si no puede hacerlo. Si se pasan estas verificaciones de errores, el código reenviará la solicitud de token al proveedor de App Attest.

Agrega eventos de Analytics

Si agregas eventos de Analytics, obtendrás mejores estadísticas sobre el éxito del lanzamiento de la Verificación de aplicaciones. Analytics ayudará a determinar si App Attest debe habilitarse para un público más amplio.

Registrar dos eventos de Analytics: AppAttestSuccess si se ejecuta correctamente y AppAttestFailure si tiene errores. Estos dos eventos de Analytics pueden ayudarte a realizar un seguimiento del éxito del lanzamiento de la Verificación de aplicaciones y a decidir si debe continuar con un lanzamiento más grande.

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. Actualiza la clase Provider Factory

Después de implementar la lógica para reenviar la solicitud de token al proveedor de App Attest y agregar algunos eventos de Analytics, debes actualizar el archivo MyAppCheckProviderFactory.class que creaste en el codelab de Verificación de aplicaciones para plataformas de Apple. Esta clase se orientará al proveedor de depuración de Verificación de aplicaciones para simuladores y, de lo contrario, se orientará a tu proveedor personalizado.

Edita el siguiente código en la clase MyAppCheckProviderFactory que creaste en el codelab de Verificación de aplicaciones de Firebase para plataformas de 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
  }
}

Confirma que estableciste AppCheckProviderFactory antes de configurar FirebaseApp:

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

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

  // ...
}

4. Agrega un parámetro de Remote Config en Firebase console

Ahora, agregarás el parámetro AppAttestEnabled de Remote Config a Firebase console . Tu método getToken requiere este parámetro.

Para crear un parámetro de Remote Config en Firebase console, haz lo siguiente :

  1. Abre Remote Config de tu proyecto y haz clic en Agregar parámetro. Si es la primera vez que usas Remote Config, haz clic en Crear configuración.
  2. En el campo Nombre del parámetro (clave), ingresa AppAttestEnabled.
  3. En el menú desplegable Tipo de datos, selecciona Booleano.
  4. En el menú desplegable Valor predeterminado, selecciona falso.

Crea un parámetro de Remote Config en Firebase console

Antes de hacer clic en Guardar, cree un valor condicional para el 10% de los usuarios:

  1. Haz clic en Agregar nuevo > Valor condicional > Crear condición nueva.
  2. En el campo Nombre, ingresa el nombre de una condición.
  3. En Se aplica si..., selecciona Usuario en percentil aleatorio, <= y, luego, ingresa 10 en el campo %.
  4. Haz clic en Crear condición.

Define una condición de Remote Config en Firebase console

Establece el valor condicional en true para que App Attest se implemente para el 10% de tus usuarios.

  1. Establece el valor en true para la condición que acabas de crear.
  2. Haz clic en Guardar.

Revisa el parámetro de Remote Config en Firebase console

Cuando termines, publica los cambios de Remote Config.

Prueba el lanzamiento en tu dispositivo

Para probar los diferentes valores de las marcas de Remote Config en tu dispositivo sin modificar el código de la app, configura un experimento con el parámetro AppAttestEnabled siguiendo el instructivo Crea experimentos de Firebase Remote Config con A/B Testing. En la sección del instructivo "Valida el experimento en un dispositivo de prueba", se explica cómo asignar diferentes valores para el dispositivo de prueba.

El paso final es usar Google Analytics para supervisar el éxito de tu lanzamiento de App Attest.

5. Revisa el éxito del lanzamiento de la Verificación de aplicaciones

Puedes medir el éxito de tu lanzamiento en el panel de eventos de Analytics. Mantente alerta a los eventos AppAttestSuccess y AppAttestFailure. Es posible que los eventos en el panel demoren hasta 24 horas en aparecer. Como alternativa, puedes habilitar la depuración y utilizar DebugView para ver los eventos de depuración más rápidamente.

De manera opcional, puedes supervisar el panel de Crashlytics para detectar aumentos en las tasas de fallas. Si quieres obtener más información para agregar Crashlytics a tu app, consulta Primeros pasos con Firebase Crashlytics.

Una vez que veas mayormente eventos AppAttestSuccess y pocos eventos AppAttestFailure, es una buena señal de que puedes aumentar el porcentaje de usuarios con App Attest habilitado modificando la condición en el parámetro AppAttestEnabled de Remote Config.

Revisa los eventos de Analytics en Firebase console

Opcional: Aprovecha el público de Google Analytics

Si quieres aprovechar aún más el evento de Analytics AppAttestEnabled, puedes crear un público de Analytics para hacer un seguimiento de los usuarios con el parámetro AppAttestEnabled configurado como verdadero.

Se lanzó App Attest con iOS 14.0. Es posible que algunos de tus usuarios no usen esta versión y, por lo tanto, no sean aptos para App Attest. Puedes registrar otro evento de Analytics para hacer un seguimiento de estos usuarios y, luego, segmentarlos para ese público por otro método de certificación, como DeviceCheck.

Opcional: Usa Crashlytics para supervisar las fallas

Para comprender mejor la estabilidad de tu app durante el lanzamiento, usa Firebase Crashlytics para supervisar las fallas y los errores recuperables.

6. ¡Felicitaciones!

Implementaste correctamente la Verificación de aplicaciones con Remote Config 🎉

Recursos adicionales: