Implementa Acceder con Google

En esta guía, se describe cómo implementar el acceso con Google y se abarcan los siguientes pasos:

  • Agrega dependencias a tu app.
  • Crea una instancia de CredentialManager.
  • Crea el flujo de la hoja inferior.
  • Crea el flujo del botón.
  • Controla la respuesta de acceso.
  • Controla los errores.
  • Controla el cierre de sesión.

Agrega dependencias a tu app

En el archivo build.gradle de tu módulo, declara dependencias con la versión más reciente de Credential Manager, Servicios de Play Auth y 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>"
}

Crea una instancia del Credential Manager

Usa el contexto de tu app o actividad para crear un objeto CredentialManager.

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

Crea el flujo de la hoja inferior

La hoja inferior es la IU integrada de Credential Manager. El uso de esta IU crea una experiencia coherente en todos los métodos de autenticación, como contraseñas, llaves de acceso y Acceder con Google.

Configura la solicitud de acceso para las cuentas autorizadas anteriormente

Intenta realizar una solicitud de acceso con Google con GetGoogleIdOption para recuperar el token de ID de Google del usuario.

Los siguientes fragmentos verifican si la cuenta es una cuenta autorizada.

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

El objeto googleIdOption de la solicitud se configura de la siguiente manera:

  • Filtra las cuentas autorizadas anteriormente: Para recuperar las cuentas autorizadas que se usaron anteriormente para acceder a tu app, establece setFilterByAuthorizedAccounts en true.

    Ten en cuenta que el valor predeterminado de setFilterByAuthorizedAccounts es true, lo que implica que el comportamiento predeterminado de la IU de la hoja inferior es mostrar solo las cuentas autorizadas anteriormente.

  • Establece el ID de cliente del servidor: Establece el parámetro setServerClientId. El webClientId es el ID de cliente web que configuraste para OAuth en tu proyecto de Google Cloud cuando completaste los requisitos previos.

  • Habilita el acceso automático (opcional): Para habilitar el acceso automático para los usuarios recurrentes, usa setAutoSelectEnabled(true) y setFilterByAuthorizedAccounts(true). Para los usuarios de tu app, esto elimina la fricción innecesaria si ya habían accedido anteriormente.

    El acceso automático solo es posible cuando se cumplen los siguientes criterios:

    • Solo hay una cuenta autorizada en el dispositivo, y esa cuenta autorizada se usó anteriormente para acceder a la app en el dispositivo. Si hay varias cuentas autorizadas en el dispositivo, se inhabilita el acceso automático.
    • El usuario no salió explícitamente de la app durante su sesión anterior.
    • El usuario no inhabilitó el acceso automático en la configuración de su Cuenta de Google.
  • Establece un nonce (opcional): Para habilitar la seguridad mejorada, establece un nonce para la verificación del servidor. Para evitar ataques de reproducción, puedes incluir un nonce para la verificación del servidor con setNonce(). Asegúrate de que tu código del servidor valide que los nonces de solicitud y respuesta sean idénticos.

    Para generar el nonce, usa una función similar a la siguiente, que genera un nonce aleatorio criptográficamente seguro de una longitud especificada y lo codifica con 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)
}

Solicitar acceso

Para verificar si el usuario tiene una cuenta autorizada en el dispositivo, llama al 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
    }
}

Configura la solicitud de acceso si no hay cuentas autorizadas disponibles

Si no hay usuarios autorizados para tu app en el dispositivo, CredentialManager devuelve un NoCredentialException. En este caso, inhabilita el filtro de cuentas autorizadas para que el usuario pueda usar otra cuenta para registrarse.

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

A continuación, solicita el acceso de manera similar a como lo hiciste para las cuentas autorizadas.

Crea el flujo del botón

Usa un botón si quieres que los usuarios puedan acceder con Google en las siguientes condiciones:

  • El usuario descartó la IU de la hoja inferior de Credential Manager.
  • No hay Cuentas de Google en el dispositivo.
  • Las cuentas existentes en el dispositivo requieren que vuelvas a realizar la autenticación.

Crea la IU del botón

Si bien esto se puede hacer con un botón de Jetpack Compose, puedes usar un ícono de marca preaprobado de la página Lineamientos de desarrollo de la marca de Acceder con Google.

Crea el flujo de acceso

Crea una solicitud de acceso con Google con GetSignInWithGoogleOption para recuperar un token de ID de Google.

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

A continuación, solicita el acceso de manera similar a como lo hiciste para la IU de la hoja inferior.

Crea la función de acceso compartido para la hoja inferior y el botón

Para controlar el acceso, completa los siguientes pasos:

  1. Usa la función getCredential() de CredentialManager. Si la respuesta es correcta, extrae el CustomCredential, que debe ser del tipo GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.
  2. Convierte el objeto en un GoogleIdTokenCredential con el método GoogleIdTokenCredential.createFrom().

  3. Valida la credencial en el servidor de tu parte externa.

  4. Asegúrate de controlar los errores de forma adecuada.

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")
        }
    }
}

Soluciona errores

Revisa los errores que se indican en Solución de problemas para asegurarte de que tu código controle todas las situaciones de error posibles.

Controla el cierre de sesión

Es importante que proporciones un mecanismo para que los usuarios salgan de tu app. Por ejemplo, un usuario podría tener varias Cuentas de Google en el dispositivo y decidir acceder desde una cuenta diferente. Puedes proporcionar esta información en tu página de configuración, por ejemplo.

Un proveedor de credenciales puede almacenar una sesión de credenciales activa y usarla para limitar las opciones de acceso en futuras solicitudes de acceso. Por ejemplo, puede priorizar la credencial activa por sobre cualquier otra credencial disponible.

Cuando un usuario salga de tu app, llama al método clearCredentialState() de la API para borrar el estado actual de las credenciales del usuario de todos los proveedores de credenciales. Esto notificará a todos los proveedores de credenciales que se debe borrar cualquier sesión de credenciales almacenada para la app determinada, lo que les proporcionará a los usuarios opciones de acceso completas la próxima vez.