Fazer o lançamento gradual do Firebase App Check usando a Configuração remota do Firebase

1. Introdução

Use o Firebase App Check com o App Attest para proteger seus serviços de back-end e verificar se as solicitações para os serviços do Firebase são provenientes do seu app autêntico.

Em geral, é recomendável integrar os usuários gradualmente ao serviço App Attest para evitar atingir os limites de cota. Para mais informações, consulte a documentação da Apple "Preparação para usar o serviço App Attest".

A capacidade de lançar atualizações de apps de forma incremental usando o recurso App Store Connect da Apple, conforme descrito em "Lançar uma atualização de versão em fases", pode facilitar o lançamento do App Check. Essa é uma solução simples e direta. No entanto, lançar uma atualização de versão do app em etapas não permite controlar o lançamento ou mudar o comportamento de apps atualizados sem publicar uma nova versão.

Uma maneira de ter mais controle sobre o lançamento do App Check com o App Attest é usar a Configuração remota do Firebase para ativar o App Check com o App Attest para uma porcentagem dos usuários do app por vez. Isso pode ajudar a evitar a limitação dos servidores de atestado. O Google Analytics pode ser usado para observar o impacto do lançamento nos usuários.

O que você aprenderá

Neste codelab em várias etapas, você vai aprender a usar a Configuração remota do Firebase para lançar o App Check no seu app.

Este codelab usa um projeto do Firebase baseado no app de início rápido DatabaseExample e integrado ao Firebase App Check, conforme descrito no codelab do Firebase App Check para plataformas Apple. O app de início rápido DatabaseExample permite que os usuários façam login e adicionem postagens usando os recursos do Firebase Realtime Database.

Você também pode adaptar as etapas deste codelab para testar seu próprio app.

Pré-requisitos

O que é necessário

  • Xcode 12.5 ou versões mais recentes
  • Para testes do App Attest:
    • Uma conta de desenvolvedor da Apple que permite criar novos identificadores de apps
    • Um aplicativo com um ID do app explícito e a capacidade do App Attest ativada. Consulte os artigos Registrar um ID do app e Ativar recursos do app se precisar de ajuda com o processo.
    • Um dispositivo iOS/iPadOS compatível com o App Attest
  • Projeto do Firebase com:
  • Acesso ao projeto do Firebase associado ao seu app, com permissões para criar e gerenciar a Configuração remota e visualizar o Google Analytics

2. Criar um provedor de atestado personalizado

Nesta etapa, vamos criar uma classe de provedor personalizada para fornecer um token somente quando o App Attest estiver ativado. A Configuração remota depende de uma instância de app do Firebase configurada, e o provedor personalizado implementado nesta etapa atua como um marcador de posição para concluir a configuração.

Para concluir as etapas a seguir, adicione Firebase, FirebaseRemoteConfig e FirebaseAnalytics na seção Frameworks, Libraries, and Embedded Content (Frameworks, bibliotecas e conteúdo incorporado) do seu app no Xcode. Para ver um exemplo de como fazer isso, consulte o codelab do Firebase App Check para plataformas da Apple.

  1. Crie um arquivo "MyAppCheckProvider" que seja uma subclasse de NSObject em conformidade com o protocolo AppCheckProvider.
  2. Inclua um método getToken() vazio que você vai preencher depois.

Confira o exemplo de código a seguir para a classe de provedor personalizada com o método getToken() vazio.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

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

Para instanciar AppAttestProvider, é necessário transmitir uma instância do FirebaseApp correspondente. Crie uma propriedade armazenada para ele e aceite como um 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) {}
}

Encaminhar a solicitação de token ao provedor do App Attest

Agora você tem tudo para encaminhar a solicitação de token ao provedor do App Attest no seu método getToken().

Observação: saiba mais sobre o método getToken() na Referência do framework FirebaseAppCheck.

Adicione o seguinte código ao 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)
}

O código anterior verifica um parâmetro booleano AppAttestEnabled da Configuração remota, que será criado mais adiante neste codelab. Se o valor for "false", o código vai falhar, indicando que o App Check não foi lançado no dispositivo atual. Se o valor for "true", o código tentará conseguir um provedor do App Attest e vai falhar se não conseguir. Se essas verificações de erros forem aprovadas, o código vai encaminhar a solicitação de token para o provedor do App Attest.

Adicionar eventos do Google Analytics

Ao adicionar eventos do Analytics, você recebe insights melhores sobre o sucesso do lançamento do App Check. O Analytics ajuda a determinar se o App Attest deve ser ativado para um público maior.

Registre dois eventos do Google Analytics: AppAttestSuccess em caso de sucesso e AppAttestFailure em caso de falha. Esses dois eventos do Google Analytics podem ajudar a acompanhar o sucesso do lançamento do App Check e decidir se um lançamento maior deve ser feito.

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. Atualizar a classe Provider Factory

Depois de implementar a lógica para encaminhar a solicitação de token ao provedor do App Attest e adicionar alguns eventos do Google Analytics, você precisa atualizar MyAppCheckProviderFactory.class, que foi criado no codelab do App Check para plataformas da Apple. Essa classe vai segmentar o provedor de depuração do App Check para simuladores e, caso contrário, vai segmentar seu provedor personalizado.

Edite o seguinte código na classe MyAppCheckProviderFactory que você criou no codelab do Firebase App Check para plataformas da 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
  }
}

Confirme se você definiu o AppCheckProviderFactory antes de configurar o FirebaseApp:

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

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

  // ...
}

4. Adicionar um parâmetro da Configuração remota no Firebase console

Agora, adicione o parâmetro da Configuração remota AppAttestEnabled ao console do Firebase . O método getToken exige esse parâmetro.

Para criar um parâmetro da Configuração remota no console do Firebase :

  1. Abra a Configuração remota do seu projeto e clique em Adicionar parâmetro. Se esta é a primeira vez que você usa a Configuração remota, clique em Criar configuração.
  2. No campo Nome do parâmetro (chave), insira AppAttestEnabled.
  3. No menu suspenso Tipo de dados, selecione Booleano.
  4. No menu suspenso Valor padrão, selecione falso.

Como criar um parâmetro da Configuração remota no console do Firebase

Antes de clicar em "Salvar", crie um valor condicional para 10% dos usuários:

  1. Clique em Adicionar novo > Valor condicional > Criar nova condição.
  2. No campo Nome, insira um nome para a condição.
  3. Em É aplicável se..., selecione Usuário em percentil aleatório, <= e insira 10 no campo %.
  4. Clique em Criar condição.

Definir uma condição da Configuração remota no console do Firebase

Defina o valor condicional como true para que o App Attest seja lançado para 10% dos seus usuários.

  1. Defina o valor como true para a condição que você acabou de criar.
  2. Clique em Salvar.

Analisar o parâmetro da Configuração remota no Firebase console

Quando terminar, publique as mudanças da Configuração remota.

Testar o lançamento no seu dispositivo

Para testar os diferentes valores de flag da Configuração remota no seu dispositivo sem modificar o código do app, configure um experimento no parâmetro AppAttestEnabled seguindo o tutorial Criar experimentos da Configuração remota do Firebase com o Teste A/B. A seção do tutorial "Validar seu experimento em um dispositivo de teste" explica como atribuir valores diferentes ao dispositivo de teste.

A etapa final é usar o Google Analytics para monitorar o sucesso do lançamento do App Attest.

5. Analisar o sucesso do lançamento do App Check

Você pode medir o sucesso do lançamento no painel "Eventos do Analytics". Monitore os eventos AppAttestSuccess e AppAttestFailure. Pode levar até 24 horas para que os eventos apareçam no painel. Você também pode ativar a depuração e usar o DebugView para ver eventos de depuração mais rapidamente.

Se quiser, monitore o painel do Crashlytics para detectar aumentos nas taxas de falha. Para mais informações sobre como adicionar o Crashlytics ao seu app, consulte Primeiros passos com o Firebase Crashlytics.

Quando você notar principalmente eventos AppAttestSuccess e poucos eventos AppAttestFailure, isso é um bom sinal de que é possível aumentar a porcentagem de usuários com o App Attest ativado. Para isso, modifique a condição no parâmetro AppAttestEnabled da Configuração remota.

Analisar eventos do Google Analytics no console do Firebase

Opcional: usar o público-alvo do Google Analytics

Se quiser aproveitar ainda mais o evento do Analytics AppAttestEnabled, crie um público-alvo do Analytics para rastrear usuários com AppAttestEnabled definido como "true".

O App Attest foi lançado com o iOS 14.0. Alguns dos seus usuários podem não estar nessa versão e, portanto, não se qualificar para o App Attest. Você pode registrar outro evento do Google Analytics para rastrear esses usuários e segmentar esse público-alvo para outro método de declaração, como o DeviceCheck.

Opcional: usar o Crashlytics para monitorar falhas

Para entender melhor a estabilidade do app durante o lançamento, use o Firebase Crashlytics para monitorar falhas e erros não fatais.

6. Parabéns!

Você lançou o App Check com a Configuração remota 🎉

Outros recursos: