Integrar o Google Cloud Fraud Defense com apps iOS

É possível integrar o Google Cloud Fraud Defense a apps iOS para avaliar os indicadores de dispositivos clientes e proteger as interações de usuários de dispositivos móveis contra abusos automatizados.

Devido à variação nos dispositivos móveis em termos de tamanho de tela, desempenho e interfaces dos apps, o teste reCAPTCHA visual de caixa de seleção (Não sou um robô) não está disponível para apps móveis iOS. Em vez disso, implemente sua própria estratégia de aplicação em níveis, como um fluxo de MFA para fornecer um caminho de resgate alternativo para tráfego suspeito.

O SDK usa reflexão e código dinâmico para permitir a atualização e o refinamento do sistema de detecção em aplicativos ou SDKs já implantados. Para evitar interferências no aplicativo, as classes disponíveis no sistema são restritas a uma lista cuidadosamente controlada.

Antes de começar

  1. Defina o SDK mínimo do seu app como iOS 15 ou crie um novo app para dispositivos móveis.

  2. Prepare seu ambiente para o Google Cloud Fraud Defense.

  3. Crie uma chave reCAPTCHA para a plataforma de apps iOS.

    Como alternativa, é possível copiar o ID de uma chave reCAPTCHA para iOS seguindo uma destas etapas:

    • Para copiar o ID de uma chave do console doGoogle Cloud , faça o seguinte:

      1. Acesse a página do Google Cloud Fraud Defense.

        Acessar o Google Cloud Fraud Defense

      2. Selecione a guia Chaves.
      3. Na lista de chaves reCAPTCHA, encontre a chave que você quer copiar e clique em .
    • Para copiar o ID de uma chave usando a API REST, use o método projects.keys.list.
    • Para copiar o ID de uma chave usando a CLI gcloud, use o comando gcloud recaptcha keys list.

  4. Ter uma conta do GitHub.

  5. Leia os detalhes de privacidade da Apple.

Preparar o ambiente do iOS

Para preparar o ambiente de desenvolvimento, faça o seguinte:

  1. Baixe e instale a versão mais recente do Xcode e crie um novo aplicativo iOS em branco com uma única visualização.

  2. Faça o download do SDK usando uma das seguintes opções:

    CocoaPods

    1. Faça o download e instale o CocoaPods.
    2. Crie um Podfile e adicione as seguintes linhas:

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'AppTarget' do
      
        # Podfiles must include use_frameworks! or
        # use_frameworks! :linkage => :static
        use_frameworks!
      
        pod "RecaptchaEnterprise", "18.10.0-beta01"
        ...
      
      end
      
    3. Instale as dependências necessárias executando pod update.

    Gerenciador de pacotes do Swift

    1. No Xcode, selecione File > Add Packages e insira o seguinte URL no campo Search ou Enter Package URL:

      https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk
      
    2. Na caixa de diálogo Xcode, insira os seguintes detalhes:

      • Nome de usuário do GitHub.
      • Um token de acesso pessoal que você criou usando as instruções do GitHub. O token de acesso pessoal precisa ter os escopos listados na caixa de diálogo Xcode Sign In.

      O Xcode instala o SDK e as dependências necessárias.

    Flutter

    Para instruções detalhadas sobre como usar o reCAPTCHA pelo Flutter, consulte a documentação do Flutter.

    React Native

    Para instruções detalhadas sobre como usar o reCAPTCHA com o React Native, consulte a documentação do React Native.

    Download direto

    1. Se você quiser baixar o SDK e as dependências dele como xcframeworks, faça o download do cliente.

Integrar o Fraud Defense ao seu app iOS

Para integrar a Fraud Defense ao seu app iOS, siga estas etapas no Xcode:

  1. Para instanciar o SDK com a chave reCAPTCHA (KEY_ID) que você criou, atualize o app com o seguinte código:

    Swift com Storyboard

    1. Atualize o ViewController.swift.

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Task {
            do {
              self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
            } catch let error as RecaptchaError {
               print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
            }
          }
        }
      }
      

      Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
            guard let client = client else {
                print("RecaptchaClient creation error: \(error).")
              return
            }
            self.recaptchaClient = client
          }
        }
      }
      

    Swift com SwiftUI

    1. Criar uma classe ViewModel.

      import RecaptchaEnterprise
      
      @MainActor class ViewModel: ObservableObject {
        private var recaptchaClient: RecaptchaClient?
      
        init() {
           Task {
            do {
              self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
            } catch let error as RecaptchaError {
               print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
            }
          }
        }
      }
      

      Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
            guard let client = client else {
                print("RecaptchaClient creation error: \(error).")
              return
            }
            self.recaptchaClient = client
          }
        }
      }
      
    2. Instancie ViewModel em ContentView.swift.

      import SwiftUI
      import RecaptchaEnterprise
      
      struct ContentView: View {
        @StateObject private var viewModel = ViewModel()
      
        var body: some View {
        }
      }
      
      struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
          ContentView()
        }
      }
      

    Objective-C

    1. Se o app estiver escrito em Objective-C, crie um arquivo Swift fictício e inclua a importação a seguir para garantir que o Xcode encontre e vincule as bibliotecas do Swift.

      import Foundation
      
    2. Para garantir que o código Swift esteja vinculado corretamente, acesse Target > Build Settings > Always Embed Swift Standard Libraries e verifique se a opção está definida como Yes.

    3. Atualize o ViewController.h.

      #import <RecaptchaEnterprise/RecaptchaEnterprise.h>
      
      @interface ViewController : UIViewController
      @property (strong, atomic) RecaptchaClient *recaptchaClient;
      @end
      
    4. Atualize o ViewController.m.

      @implementation ViewController
      [Recaptcha fetchClientWithSiteKey:@"KEY_ID"
            completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
              if (!recaptchaClient) {
                NSLog(@"%@", (RecaptchaError *)error.errorMessage);
                return;
              }
              self->_recaptchaClient = recaptchaClient;
            }
      ];
      @end
      

    A inicialização do SDK pode levar vários segundos para ser concluída. Para reduzir essa latência, inicialize o cliente o mais cedo possível, como durante a chamada onCreate() de uma classe Application personalizada. Não bloqueie elementos da interface no SDK do reCAPTCHA.

  2. Crie um botão para chamar o reCAPTCHA e acionar execute().

    Swift com Storyboard

    1. No storyboard, crie um botão.
    2. Crie uma ação em ViewController vinculada ao botão que você criou.
    3. Chame o método execute() transmitindo uma ação Login para retornar um token reCAPTCHA usando o seguinte snippet de código:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      Task {
        do {
          let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login)
          print(token)
        } catch let error as RecaptchaError {
          print(error.errorMessage)
        }
      }
      

      Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
      

    Swift com SwiftUI

    1. Atualize ViewModel.swift com o código de execução:

      import RecaptchaEnterprise
      
      @MainActor class ViewModel: ObservableObject {
      
        func execute() {
          guard let recaptchaClient = self.recaptchaClient else {
            print("Client not initialized correctly.")
            return
          }
      
          Task {
            do {
              let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login)
              print(token)
            } catch let error as RecaptchaError {
              print(error.errorMessage)
            }
          }
        }
      }
      

      Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
      
    2. Atualize o ContentView.swift.

      import SwiftUI
      import RecaptchaEnterprise
      
      struct ContentView: View {
        @StateObject private var viewModel = ViewModel()
      
        var body: some View {
      
          Button {
            viewModel.execute()
          } label: {
            Text("Execute")
          }.padding()
      
          Spacer()
        }
      }
      
      struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
          ContentView()
        }
      }
      

    Objective-C

    1. No storyboard, crie um botão.
    2. Crie uma ação em ViewController vinculada ao botão que você criou.
    3. Chame o método execute() transmitindo uma ação Login para retornar um token reCAPTCHA:

      if (!self->_recaptchaClient) {
        return;
      }
      
      [recaptchaClient execute:RecaptchaAction.login
          completion:^void(NSString* _Nullable  token, NSError* _Nullable error) {
        if (!token) {
          NSLog (@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        NSLog (@"%@", token);
      }];
      

    A API execute do cliente pode levar vários segundos para ser concluída, como em condições de rede lentas ou se estiver aguardando a conclusão da inicialização em segundo plano. Verifique se as chamadas de execute() não bloqueiam um evento UI, como pressionar um botão.

  3. Teste o aplicativo:

    1. O reCAPTCHA usa o App Attest da Apple como parte do mecanismo de detecção. Se você não planeja usar uma chave de teste com uma pontuação fixa para o desenvolvimento local, faça o seguinte:

      1. No Xcode, adicione o recurso App Attest ao app.

      2. No arquivo .entitlements do projeto, defina o ambiente do App Attest como production.

    2. Para limpar o ambiente de build do Xcode, no menu Product, clique em Clean Build Folder.

    3. Para executar o aplicativo, no menu Product, clique em Run.

    4. No aplicativo carregado, clique no botão que você criou anteriormente.

    5. Observe a janela de saída de depuração para ver um token do reCAPTCHA (string alfanumérica), que é retornado se a integração for bem-sucedida.

Migrar do método getClient para o método fetchClient

O método fetchClient retorna um RecaptchaClient que tenta fazer a inicialização novamente em caso de falhas de rede. Se o app não tiver acesso à rede quando o cliente for criado, ele vai continuar tentando e será inicializado quando uma rede for adquirida.

Se você chamar execute(timeout) e o cliente ainda não estiver pronto, ele vai tentar fazer a inicialização antes de retornar um token ou um RecaptchaError.

O exemplo a seguir mostra como migrar de getClient para fetchClient.

Swift com Storyboard

// Migrate from getClient
func initializeWithGetClient() {
  Task {
    do {
      self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

// Migrate to fetchClient
func initializeWithFetchClient() {
  Task {
    do {
      self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

// Migrate from getClient
override func initializeWithGetClient() {
  Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

// Migrate to fetchClient
override func initializeWithFetchClient() {
  Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

Swift com SwiftUI

// Migrate from getClient
func initializeWithGetClient() {
    Task {
    do {
      self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

// Migrate to fetchClient
func initializeWithFetchClient() {
    Task {
    do {
      self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

Se a versão mínima do SO do seu aplicativo for anterior à 13, use um encerramento final:

// Migrate from getClient
func initializeWithGetClient() {
  super.viewDidLoad()
  Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

// Migrate to fetchClient
func initializeWithFetchClient() {
  super.viewDidLoad()
  Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

Objective-C

// Migrate from getClient
@implementation ViewController
[Recaptcha getClientWithSiteKey:@"KEY_ID"
      completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
        if (!recaptchaClient) {
          NSLog(@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        self->_recaptchaClient = recaptchaClient;
      }
];
@end

// Migrate to fetchClient
@implementation ViewController
[Recaptcha fetchClientWithSiteKey:@"KEY_ID"
      completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
        if (!recaptchaClient) {
          NSLog(@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        self->_recaptchaClient = recaptchaClient;
      }
];
@end

Definir um tempo limite para chamadas de API

É possível especificar um valor de tempo limite para as APIs execute usando a propriedade withTimeout.

Swift

  1. Defina o tempo limite ao chamar execute.

      Task {
        do {
          let token = try await recaptchaClient.execute(
            withAction: RecaptchaAction.login,
            withTimeout: 10000)
          print(token)
        } catch let error as RecaptchaError {
          print(error.errorMessage)
        }
      }
    

    Se a versão mínima do SO do seu aplicativo for anterior à 13, use um fechamento final:

      recaptchaClient.execute(
        withAction: RecaptchaAction.login,
        withTimeout: 10000
      ) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
    

Objective-C

  1. Defina o tempo limite ao chamar execute.

      [recaptchaClient execute:RecaptchaAction.login
          withTimeout:10000.0
          completion:^void(NSString* _Nullable  token, NSError* _Nullable error) {
        if (!token) {
          NSLog (@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        NSLog (@"%@", token);
      }];
    

Tratar erros

Se o app não conseguir se comunicar com o serviço reCAPTCHA, pode ser porque a API encontrou um erro. Adicione uma lógica ao app para lidar com esses erros de maneira adequada.

Para mais detalhes sobre mitigações de erros comuns da API, consulte RecaptchaErrorCode.

Referência da API

Para uma referência completa da API reCAPTCHA para iOS, consulte RecaptchaEnterprise.

A seguir

  • Para avaliar o token de resposta reCAPTCHA, crie uma avaliação.