Implementar o Fazer login com o Google

Este guia descreve como implementar o recurso Fazer login com o Google e aborda as seguintes etapas:

  • Adicione dependências ao app.
  • Instancie CredentialManager.
  • Crie o fluxo da página inferior.
  • Crie o fluxo de botões.
  • Processe a resposta de login.
  • Tratar erros.
  • Processar a saída.

Adicionar dependências ao app

No arquivo build.gradle do módulo, declare dependências usando a versão mais recente do Credential Manager, autenticação do Google Play Services e googleid:

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha01")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha01")
    implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>")
}

Groovy

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

Instanciar o Credential Manager

Use o contexto do app ou da atividade para criar um objeto CredentialManager.

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

Criar o fluxo da página inferior

A página inferior é a interface integrada do Credential Manager. O uso dessa interface cria uma experiência consistente em todos os métodos de autenticação, como senhas, chaves de acesso e Fazer login com o Google.

Configurar a solicitação de login para contas autorizadas anteriormente

Tente uma solicitação de login do Google com GetGoogleIdOption para extrair o token de ID do Google do usuário.

Os snippets a seguir verificam se a conta é autorizada.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(true)
    .setServerClientId(WEB_CLIENT_ID)
    .setAutoSelectEnabled(true)
    .setNonce(generateSecureRandomNonce())
    .build()

O objeto de solicitação googleIdOption é configurado da seguinte maneira:

  • Filtrar contas autorizadas anteriormente:para recuperar as contas autorizadas que já foram usadas para fazer login no app, defina setFilterByAuthorizedAccounts como true.

    Observação: o valor padrão de setFilterByAuthorizedAccounts é true. Isso significa que o comportamento padrão da interface do usuário da página inferior é mostrar apenas contas autorizadas anteriormente.

  • Defina o ID do cliente do servidor:defina o parâmetro setServerClientId. O webClientId é o ID do cliente da Web que você configurou para o OAuth no projeto do Google Cloud ao concluir os pré-requisitos.

  • Ativar o login automático (opcional): para ativar o login automático para usuários recorrentes, use setAutoSelectEnabled(true) e setFilterByAuthorizedAccounts(true). Para os usuários do app, isso remove atritos desnecessários se eles já estavam conectados.

    O login automático só é possível quando os seguintes critérios são atendidos:

    • Há apenas uma conta autorizada no dispositivo, e ela foi usada anteriormente para fazer login no app. Várias contas autorizadas no dispositivo desativam o login automático.
    • O usuário não saiu explicitamente do app na sessão anterior.
    • O usuário não desativou o login automático nas configurações da Conta do Google.
  • Defina um valor de uso único (opcional): para ativar a segurança aprimorada, defina um valor de uso único para a verificação do lado do servidor. Para evitar ataques de repetição, inclua um nonce para verificação do lado do servidor com setNonce(). Verifique se o código do lado do servidor valida se os nonces de solicitação e resposta são idênticos.

    Para gerar o nonce, use uma função semelhante à seguinte, que gera um nonce aleatório criptograficamente forte de um comprimento especificado e o codifica usando Base64:

fun generateSecureRandomNonce(byteLength: Int = 32): String {
    val randomBytes = ByteArray(byteLength)
    SecureRandom().nextBytes(randomBytes)
    return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}

Pedir login

Verifique se o usuário tem uma conta autorizada no dispositivo chamando o método getCredential:

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

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

Configurar a solicitação de login se não houver contas autorizadas disponíveis

Se não houver usuários autorizados para seu app no dispositivo, CredentialManager vai retornar um NoCredentialException. Nesse cenário, desative o filtro de contas autorizadas para que o usuário possa usar outra conta para se inscrever.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(false)
    .setServerClientId(WEB_CLIENT_ID)
    .setNonce(generateSecureRandomNonce())
    .build()

Em seguida, solicite o login da mesma forma que fez para as contas autorizadas.

Criar o fluxo de botões

Use um botão se quiser que os usuários possam fazer login com o Google nas seguintes condições:

  • O usuário dispensou a interface da página inferior do Credential Manager.
  • Não há Contas do Google no dispositivo.
  • As contas atuais no dispositivo precisam ser autenticadas de novo.

Criar a interface do botão

Embora isso possa ser feito com um botão do Jetpack Compose, use um ícone de marca pré-aprovado na página Diretrizes de branding do Fazer login com o Google.

Criar o fluxo de login

Crie uma solicitação de Login do Google com GetSignInWithGoogleOption para extrair um token de ID do Google.

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
    serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
    .build()

Em seguida, solicite o login da mesma forma que fez para a UI da página inferior.

Crie a função de login compartilhada para a página inferior e o botão.

Para processar o login, siga estas etapas:

  1. Use a função getCredential() do CredentialManager. Se a resposta for bem-sucedida, extraia o CustomCredential, que deve ser do tipo GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.
  2. Converta o objeto em um GoogleIdTokenCredential usando o método GoogleIdTokenCredential.createFrom().

  3. Valide a credencial no servidor da terceira parte confiável.

  4. Verifique se você está processando os erros de maneira adequada.

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

    when (credential) {
        is CustomCredential -> {
            if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                try {
                    // Use googleIdTokenCredential and extract the ID for server-side validation.
                    val googleIdTokenCredential = GoogleIdTokenCredential
                        .createFrom(credential.data)
                } catch (e: GoogleIdTokenParsingException) {
                    Log.e(TAG, "Received an invalid google id token response", e)
                }
            } else {
                // Catch any unrecognized credential type here.
                Log.e(TAG, "Unexpected type of credential")
            }
        }

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

Solucionar erros

Analise os erros listados em Solução de problemas para garantir que seu código processe todos os cenários de erro possíveis.

Processar a saída

É importante oferecer um mecanismo para que os usuários saiam do seu app. Por exemplo, um usuário pode ter várias Contas do Google no dispositivo e decidir fazer login com uma conta diferente. Você pode fornecer isso na página de configurações, por exemplo.

Um provedor de credenciais pode armazenar uma sessão de credenciais ativa e usá-la para limitar as opções de login em solicitações futuras. Por exemplo, ele pode priorizar a credencial ativa em vez de qualquer outra disponível.

Quando um usuário sair do app, chame o método clearCredentialState() da API para limpar o estado atual da credencial do usuário de todos os provedores de credenciais. Isso vai notificar todos os provedores de credenciais de que qualquer sessão de credencial armazenada para o app em questão deve ser limpa, oferecendo aos usuários opções de login completas na próxima vez.