Integrar o Gerenciador de credenciais ao recurso "Fazer login com o Google"

Página inferior com o Gerenciador de credenciais ativado mostrando várias identidades para selecionar.
Figura 1. Como a caixa de diálogo da página inferior aparece com o recurso Fazer login com o Google após a integração com a API Credential Manager.

Este documento explica como migrar a caixa de diálogo Fazer login com o Google dos Serviços de Identificação do Google (GIS, na sigla em inglês) para a API Credentials Manager usando a biblioteca auxiliar Google ID.

Um app que usa a API Credential Manager é configurado para apresentar ao usuário final uma interface do Android consistente. Ela permite que o usuário selecione em uma lista de opções de login salvas, incluindo contas ativadas com chave de acesso. Essa é a API Android recomendada para consolidar diferentes tipos de credenciais e provedores. No Android 14 e versões mais recentes, os usuários também podem aproveitar gerenciadores de senhas de terceiros com a API Credential Manager.

Declarar dependências

No arquivo build.gradle do módulo, declare as dependências usando a versão mais recente:

dependencies {
  // ... other dependencies

  implementation "androidx.credentials:credentials:<latest version>"
  implementation "androidx.credentials:credentials-play-services-auth:<latest version>"
  implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

Siga as instruções para configurar o projeto do Console de APIs do Google. Substitua as orientações sobre a inclusão de dependências pelas instruções mencionadas acima.

Instanciar uma solicitação de login do Google

Para iniciar sua implementação, instancie uma solicitação de login do Google. Use GetGoogleIdOption para extrair o token de ID do Google de um usuário.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .build();

Primeiro, chame a API com o parâmetro setFilterByAuthorizedAccounts definido como true. Se não houver credenciais disponíveis, chame a API de novo e defina setFilterByAuthorizedAccounts como false.

Se você quiser fazer login dos usuários automaticamente quando possível, ative o recurso com setAutoSelectEnabled na sua solicitação GetGoogleIdOption. O login automático é possível quando os critérios abaixo são atendidos:

  • O usuário tem exatamente uma credencial salva para o app. Ou seja, uma senha ou Conta do Google salva.
  • O usuário não desativou o login automático nas configurações da Conta do Google.

Para melhorar a segurança de login e evitar ataques de repetição, use setNonce para incluir um valor de uso único em cada solicitação. Saiba mais sobre como gerar um valor de uso único.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>);
  .build();

Fazer login com o Google

As etapas para configurar um fluxo do recurso Fazer login com o Google são estas:

  1. Instancie a GetCredentialRequest e adicione a googleIdOption criada acima para extrair as credenciais.
  2. Transmita essa solicitação para a chamada getCredential() (Kotlin) ou getCredentialAsync() (Java) para extrair as credenciais disponíveis do usuário.
  3. Quando a API for bem-sucedida, extraia a CustomCredential que contém o resultado dos dados GoogleIdTokenCredential.
  4. O tipo de CustomCredential precisa ser igual ao valor de GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL. Converta o objeto em uma GoogleIdTokenCredential usando o método GoogleIdTokenCredential.createFrom.
  5. Se a conversão for bem-sucedida, extraia e valide o ID da GoogleIdTokenCredential, depois, autentique a credencial no seu servidor.
  6. Se a conversão falhar com uma GoogleIdTokenParsingException, talvez seja necessário atualizar a versão da biblioteca do recurso Fazer login com o Google.
  7. Capture todos os tipos de credenciais personalizadas não reconhecidos.

Kotlin

val request: GetCredentialRequest = Builder()
  .addGetCredentialOption(googleIdOption)
  .build()

coroutineScope.launch {
  try {
    val result = credentialManager.getCredential(
      request = request,
      context = activityContext,
    )
    handleSignIn(result)
  } catch (e: GetCredentialException) {
    handleFailure(e)
  }
}

fun handleSignIn(result: GetCredentialResponse) {
  // Handle the successfully returned credential.
  val credential = result.credential

  when (credential) {
    is PublicKeyCredential -> {
      // Share responseJson such as a GetCredentialResponse on your server to
      // validate and authenticate
      responseJson = credential.authenticationResponseJson
    }

    is PasswordCredential -> {
      // Send ID and password to your server to validate and authenticate.
      val username = credential.id
      val password = credential.password
    }

    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract id to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      } else {
        // Catch any unrecognized custom credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

    else -> {
      // Catch any unrecognized credential type here.
      Log.e(TAG, "Unexpected type of credential")
    }
  }
}

Java

GetCredentialRequest request = new GetCredentialRequest.Builder()
  .addGetCredentialOption(googleIdOption)
  .build();

// Launch sign in flow and do getCredential Request to retrieve the credentials
credentialManager.getCredentialAsync(
  requireActivity(),
  request,
  cancellationSignal,
  <executor>,
  new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
    @Override
    public void onResult(GetCredentialResponse result) {
      handleSignIn(result);
    }

    @Override
    public void onError(GetCredentialException e) {
      handleFailure(e);
    }
  }
);

public void handleSignIn(GetCredentialResponse result) {
  // Handle the successfully returned credential.
  Credential credential = result.getCredential();

  if (credential instanceof PublicKeyCredential) {
    String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson();
    // Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate
  } else if (credential instanceof PasswordCredential) {
    String username = ((PasswordCredential) credential).getId();
    String password = ((PasswordCredential) credential).getPassword();
    // Use id and password to send to your server to validate and authenticate
  } else if (credential instanceof CustomCredential) {
    if (GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(credential.getType())) {
      try {
        // Use googleIdTokenCredential and extract id to validate and
        // authenticate on your server
        GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(((CustomCredential) credential).getData());
      } catch (GoogleIdTokenParsingException e) {
        Log.e(TAG, "Received an invalid Google ID token response", e);
      }
    } else {
      // Catch any unrecognized custom credential type here.
      Log.e(TAG, "Unexpected type of credential");
    }
  } else {
    // Catch any unrecognized credential type here.
    Log.e(TAG, "Unexpected type of credential");
  }
}

Botão "Fazer login com o Google"

O botão Fazer login com o Google pode ser usado com o Gerenciador de credenciais junto à biblioteca auxiliar Google ID mais recente. Para acionar o fluxo do botão "Fazer login com o Google", use GetSignInWithGoogleOption em vez de GetGoogleIdOption e processe o GoogleIdTokenCredential assim como antes.

Inscrever-se com o Google

Se nenhum resultado for retornado após definir setFilterByAuthorizedAccounts como true (verdadeiro) ao instanciar a solicitação GetGoogleIdOption e transmitir para GetCredentialsRequest, isso indica que não há contas autorizadas para fazer login. Agora, defina setFilterByAuthorizedAccounts(false) e chame Inscrever-se com o Google.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(SERVER_CLIENT_ID)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(SERVER_CLIENT_ID)
  .build();

Depois de instanciar a solicitação de inscrição do Google, inicie o fluxo de autenticação de maneira semelhante, conforme mencionado na seção Fazer login com o Google.

Processar a saída

Quando um usuário sair do app, chame o método clearCredentialState() da API para limpar o estado atual da credencial do usuário e redefinir o estado interno de login.