Implemente gradualmente o Firebase App Check usando o Firebase Remote Config

1. Introdução

Você pode usar o Firebase App Check com o App Attest para proteger seus serviços de back-end e verificar se as solicitações aos serviços do Firebase vêm do seu aplicativo autêntico.

Geralmente, é recomendado integrar os usuários gradualmente ao serviço App Attest para evitar atingir os limites de cota. Para obter mais informações, consulte a documentação " Preparando para usar o serviço App Attest " da Apple.

A capacidade de lançar atualizações de aplicativos de forma incremental usando o recurso App Store Connect da Apple, conforme descrito em " Liberando uma atualização de versão em fases ", pode tornar a implementação do App Check mais suave. Esta é uma solução direta e simples. No entanto, lançar uma atualização de versão do aplicativo em etapas não permite controlar a implementação ou alterar o comportamento de aplicativos atualizados existentes sem publicar uma nova versão do aplicativo.

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

O que você aprenderá

Neste codelab de várias etapas, você aprenderá a usar o Firebase Remote Config para implementar o App Check no seu app.

Este codelab usa um projeto do Firebase baseado no aplicativo de início rápido DatabaseExample e integrado ao Firebase App Check, conforme descrito no codelab Firebase App Check para plataformas Apple . O aplicativo 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 você precisará

  • Xcode 12.5+
  • Para testes do App Attest:
  • Projeto Firebase com:
  • Acesso ao projeto do Firebase associado ao seu aplicativo, com permissões para criar e gerenciar a Configuração remota e visualizar o Google Analytics

2. Crie um provedor de atestado personalizado

Nesta etapa, criaremos uma classe de provedor personalizada para fornecer um token somente quando o App Attest estiver habilitado. A Configuração remota depende de uma instância configurada do aplicativo Firebase, e o provedor personalizado implementado nesta etapa atua como espaço reservado para concluir a configuração.

Para concluir as etapas a seguir, você precisará adicionar Firebase , FirebaseRemoteConfig e FirebaseAnalytics na seção Frameworks, Libraries, and Embedded Content do seu aplicativo no Xcode. Para obter um exemplo de como fazer isso, consulte o codelab de verificação do aplicativo Firebase para plataformas 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ê preencherá mais tarde.

Consulte o código de exemplo 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 , você precisará passar uma instância do FirebaseApp correspondente. Crie uma propriedade armazenada para ele e aceite-a como 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) {}
}

Encaminhe a solicitação de token para o provedor do App Attest

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

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

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 do Configuração remota (esse parâmetro do Configuração remota será criado posteriormente no codelab). Se o valor for falso, o código falhará, indicando que o App Check não foi implementado 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ê obtém melhores insights sobre o sucesso da implementação do App Check. O Analytics ajudará a determinar se o App Attest deve ser habilitado para um público maior.

Registre dois eventos do Analytics: AppAttestSuccess em caso de sucesso e AppAttestFailure em caso de falha. Esses dois eventos do Analytics podem ajudar a monitorar o sucesso da implementação do App Check e ajudá-lo a decidir se uma implementação 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. Atualize 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 Analytics, você precisa atualizar MyAppCheckProviderFactory.class que você criou no codelab do App Check para plataformas Apple . Esta classe terá como alvo o provedor de depuração do App Check para simuladores e, caso contrário, terá como alvo seu provedor personalizado.

Edite o seguinte código na classe MyAppCheckProviderFactory que você criou no codelab do Firebase App Check para plataformas 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 AppCheckProviderFactory antes de configurar FirebaseApp :

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

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

  // ...
}

4. Adicione um parâmetro do Configuração remota no console do Firebase

Agora você adicionará o parâmetro AppAttestEnabled do Configuração remota ao console do Firebase. Seu método getToken requer este parâmetro.

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

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

Criando parâmetro de 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 de condição.
  3. Em Aplica-se se... , selecione Usuário em percentil aleatório , <= e insira 10 no campo % .
  4. Clique em Criar condição .

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

Defina o valor condicional como verdadeiro para que o App Attest seja implementado para 10% dos seus usuários.

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

Revendo o parâmetro do Configuração remota no Console do Firebase

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

Teste a implementação no seu dispositivo

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

A etapa final é usar o Google Analytics para monitorar o sucesso da implementação do App Attest.

5. Revise o sucesso da implementação do AppCheck

Você pode medir o sucesso de sua implementação no painel de eventos do Analytics. Fique atento aos eventos AppAttestSuccess e AppAttestFailure . Pode levar até 24 horas para ver os eventos no painel. Como alternativa, você pode ativar a depuração e usar o DebugView para ver os eventos de depuração mais rapidamente.

Opcionalmente, você pode monitorar o painel do Crashlytics em busca de aumentos nas taxas de falhas. Para obter mais informações sobre como adicionar o Crashlytics ao seu aplicativo, consulte Primeiros passos com o Firebase Crashlytics .

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

Revisão de eventos do Analytics no Firebase console

Opcional: aproveite o público do Google Analytics

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

O App Attest foi lançado com iOS 14.0. Alguns de seus usuários podem não estar nesta versão e, portanto, não estão qualificados para o App Attest. Você pode registrar outro evento do Analytics para rastrear esses usuários e, em seguida, direcionar esse público para outro método de atestado, como DeviceCheck .

Opcional: use o Crashlytics para monitorar falhas

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

6. Parabéns!

Você implementou o App Check com Configuração remota com sucesso 🎉

Recursos adicionais: