Lançar gradualmente o 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 Preparing to Use the App Attest Service (em inglês) da Apple.

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 a atualização de uma versão do app em etapas não permite controlar o lançamento ou mudança de comportamento dos apps atualizados sem publicar uma nova versão.

Uma maneira de ter mais controle sobre o App Check com o lançamento do 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 seu app ao mesmo tempo. 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 de várias etapas, você aprenderá a usar a Configuração remota do Firebase para implantar o App Check no seu app.

Este codelab usa um projeto do Firebase baseado no app de início rápido do DatabaseExample integrado ao Firebase App Check, conforme descrito no codelab do Firebase App Check para plataformas da Apple. Com o app de início rápido do DatabaseExample, os usuários podem fazer login e adicionar 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 mais recente
  • 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 com o recurso App Attest ativado. Consulte os artigos Registrar um ID de app e Ativar recursos do app se precisar de ajuda no 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. O Configuração remota depende de uma instância do app Firebase configurada, e o provedor personalizado implementado nesta etapa atua como marcador de posição para concluir a configuração.

Para concluir as etapas a seguir, será necessário adicionar Firebase, FirebaseRemoteConfig e FirebaseAnalytics à seção Frameworks, bibliotecas e conteúdo incorporado do app no Xcode. Para conferir um exemplo de como fazer isso, consulte o codelab da Verificação de apps do Firebase 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 mais tarde.

Confira o código de exemplo abaixo 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 o AppAttestProvider, você precisará transmitir uma instância do FirebaseApp correspondente. Crie uma propriedade armazenada para ela e a aceite como um parâmetro 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 para o provedor do App Attest

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

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

Adicione o seguinte código ao seu 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. Esse parâmetro será criado posteriormente no codelab. Se o valor for "false", o código falhará, indicando que o App Check não foi implantado no dispositivo atual. Se o valor for verdadeiro, o código tentará obter um provedor do App Attest e falhará se não conseguir. Se essas verificações de erro forem aprovadas, o código encaminhará a solicitação de token para o provedor do App Attest.

Adicionar eventos do 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 Analytics podem ajudar a acompanhar o sucesso do lançamento do App Check e ajudar você a decidir se um lançamento maior deve prosseguir.

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 da 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 Analytics, você precisa atualizar o MyAppCheckProviderFactory.class criado no codelab do App Check para plataformas da Apple. Essa classe terá como alvo o provedor de depuração do App Check para simuladores. Caso contrário, seu provedor personalizado será destinado.

Edite o código a seguir 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 que 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 Console do Firebase

Agora, você adicionará o parâmetro AppAttestEnabled da Configuração remota ao Console do Firebase . O método getToken exige esse parâmetro.

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

  1. Abra a Configuração remota do seu projeto e clique em Adicionar parâmetro. Se você estiver usando a Configuração remota pela primeira vez, clique em Criar configuração.
  2. No campo Nome do parâmetro (chave), insira AppAttestEnabled.
  3. Na lista suspensa Tipo de dados, selecione Booleano.
  4. No menu suspenso Valor padrão, selecione false.

Como criar o 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 na porcentagem aleatória, <=, e depois insira 10 no campo %.
  4. Clique em Criar condição.

Como 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 usuários.

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

revisar o parâmetro da Configuração remota no Console do Firebase;

Quando terminar, publique as alterações da Configuração remota.

Testar o lançamento no seu dispositivo

Para testar os diferentes valores de sinalização 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 para esse dispositivo.

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

5. Analise o sucesso do seu lançamento do AppCheck

Você pode medir o sucesso do lançamento no painel "Eventos" do Analytics. Fique atento aos eventos AppAttestSuccess e AppAttestFailure. Pode levar até 24 horas para que os eventos apareçam no painel. Como alternativa, é possível ativar a depuração e usar o DebugView para ver eventos de depuração mais rapidamente.

Outra opção é monitorar o painel do Crashlytics para conferir aumentos nas taxas de falhas. Para mais informações sobre como adicionar o Crashlytics ao seu app, consulte Primeiros passos com o Firebase Crashlytics.

Quando você vê principalmente eventos AppAttestSuccess e alguns eventos AppAttestFailure, é um bom sinal de que você pode aumentar a porcentagem de usuários com o App Attest ativado modificando a condição no parâmetro AppAttestEnabled da Configuração remota.

Analisar eventos do Google Analytics no Console do Firebase

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

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

O App Attest foi lançado com o iOS 14.0. Talvez alguns dos seus usuários não estejam usando essa versão e, portanto, não estejam qualificados para o App Attest. Você pode registrar outro evento do Google Analytics para rastrear esses usuários e depois segmentar esse público-alvo para outro método de atestado, 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ê implementou o App Check com a Configuração remota 🎉

Recursos adicionais: