Cómo integrar el Administrador de credenciales con Acceder con Google

Acceder con Google te ayuda a integrar rápidamente la autenticación de usuarios en tu app para Android. Los usuarios pueden usar su Cuenta de Google para acceder a tu app, dar su consentimiento y compartir de forma segura la información de su perfil con tu app. La biblioteca de Jetpack para el Administrador de credenciales de Android simplifica esta integración y ofrece una experiencia coherente en todos los dispositivos Android con una sola API.

Este documento te guiará en la implementación de Acceder con Google en las apps para Android, la configuración de la IU del botón de Acceder con Google y la configuración de las experiencias de registro y acceso optimizadas para la app con un solo toque. Para una migración fluida de los dispositivos, Acceder con Google admite el acceso automático, y su naturaleza multiplataforma en Android, iOS y plataformas web te ayuda a proporcionar acceso para tu app en cualquier dispositivo.

Para configurar Acceder con Google, sigue estos dos pasos principales:

Configura Acceder con Google como una opción para la IU de la hoja inferior del Administrador de credenciales. Se puede configurar para solicitarle automáticamente al usuario que acceda. Si implementaste llaves de acceso o contraseñas, puedes solicitar todos los tipos de credenciales relevantes de forma simultánea para que el usuario no tenga que recordar la opción que usó antes para acceder.

Hoja inferior del Administrador de credenciales
Figura 1: IU de selección de credenciales de la hoja inferior del Administrador de credenciales

Agrega el botón Acceder con Google a la IU de tu app. El botón Acceder con Google ofrece a los usuarios una forma optimizada de usar sus Cuentas de Google existentes para registrarse en apps para Android o acceder a ellas. Los usuarios harán clic en el botón Acceder con Google si descartan la IU de la hoja inferior o si quieren usar su Cuenta de Google de forma explícita para registrarse y acceder. Para los desarrolladores, esto facilita la integración de los usuarios y reduce las dificultades durante el registro.

Animación que muestra el flujo de Acceder con Google
Figura 2: IU del botón de Acceder con Google del Administrador de credenciales

En este documento, se explica cómo integrar el botón Acceder con Google y el diálogo de la hoja inferior en la API de Credential Manager con la biblioteca auxiliar de ID de Google.

Configura tu proyecto de la Consola de APIs de Google

  1. Abre tu proyecto en la Consola de APIs o crea uno si aún no lo tienes.
  2. En la página de la pantalla de consentimiento de OAuth, asegúrate de que toda la información esté completa y sea precisa.
    1. Asegúrate de que tu app tenga asignados un nombre, un logotipo y una página principal de la app correctos. Estos valores se mostrarán a los usuarios en la pantalla de consentimiento de Acceder con Google en el registro y en la pantalla de apps y servicios de terceros.
    2. Asegúrate de especificar las URLs de la política de privacidad y las condiciones del servicio de tu app.
  3. En la página Credenciales, crea un ID de cliente de Android para la app si aún no lo tienes. Deberás especificar el nombre del paquete y la firma SHA-1 de tu app.
    1. Ve a la página Credenciales.
    2. Haz clic en Crear credenciales > ID de cliente de OAuth.
    3. Selecciona el tipo de aplicación Android.
  4. En la página Credenciales, crea un nuevo ID de cliente de "aplicación web" si aún no lo has hecho. Por ahora, puedes ignorar los campos "Orígenes de JavaScript autorizados" y "URI de redireccionamiento autorizados". Este ID de cliente se usará para identificar tu servidor de backend cuando se comunique con los servicios de autenticación de Google.
    1. Ve a la página Credenciales.
    2. Haz clic en Crear credenciales > ID de cliente de OAuth.
    3. Selecciona el tipo de aplicación web.

Cómo declarar dependencias

En el archivo build.gradle del módulo, declara las dependencias con la versión más reciente del Administrador de credenciales:

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

Cómo crear una instancia de una solicitud de acceso con Google

Para comenzar con la implementación, crea una instancia de una solicitud de acceso con Google. Usa GetGoogleIdOption para recuperar el token de ID de Google de un usuario.

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

Primero, verifica si el usuario tiene cuentas que se usaron anteriormente para acceder a tu app. Para ello, llama a la API con el parámetro setFilterByAuthorizedAccounts configurado como true. Los usuarios pueden elegir entre las cuentas disponibles para acceder.

Si no hay Cuentas de Google autorizadas disponibles, se le debe solicitar al usuario que se registre con cualquiera de ellas. Para ello, pídele al usuario que vuelva a llamar a la API y configura setFilterByAuthorizedAccounts como false. Obtén más información sobre cómo registrarte.

Habilitar el acceso automático para los usuarios recurrentes (recomendado)

Los desarrolladores deben habilitar el acceso automático para los usuarios que se registran con su única cuenta. Esto proporciona una experiencia fluida en todos los dispositivos, especialmente durante la migración, en la que los usuarios pueden recuperar rápidamente el acceso a su cuenta sin volver a ingresar las credenciales. Esto quita las fricciones innecesarias para los usuarios cuando ya accedieron a sus cuentas.

Para habilitar el acceso automático, usa setAutoSelectEnabled(true). El acceso automático solo es posible cuando se cumplen los siguientes criterios:

  • Existe una sola credencial que coincide con la solicitud, que puede ser una Cuenta de Google o una contraseña, y esta credencial coincide con la cuenta predeterminada en el dispositivo con Android.
  • El usuario no salió de la cuenta explícitamente.
  • El usuario no inhabilitó el acceso automático en la configuración de su Cuenta de Google.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Recuerda controlar el cierre de sesión correctamente cuando implementes el acceso automático, para que los usuarios puedan elegir siempre la cuenta adecuada después de salir de forma explícita de tu app.

Establece un nonce para mejorar la seguridad

Para mejorar la seguridad de acceso y evitar ataques de repetición, agrega setNonce para incluir un nonce en cada solicitud. Obtén más información para generar un nonce.

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

Crea el flujo de Acceder con Google

Los pasos para configurar un flujo de Acceder con Google son los siguientes:

  1. Crea una instancia de GetCredentialRequest y agrega el googleIdOption creado anteriormente para recuperar las credenciales.
  2. Pasa esta solicitud a la llamada a getCredential() (Kotlin) o a getCredentialAsync() (Java) para recuperar las credenciales disponibles del usuario.
  3. Una vez que la API funcione de forma correcta, extrae el objeto CustomCredential que contiene el resultado de los datos de GoogleIdTokenCredential.
  4. El tipo de CustomCredential debe ser igual al valor de GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL. Convierte el objeto en una GoogleIdTokenCredential con el método GoogleIdTokenCredential.createFrom.
  5. Si la conversión se realiza correctamente, extrae el ID de GoogleIdTokenCredential, valida y autentica la credencial en tu servidor.

  6. Si la conversión falla con una GoogleIdTokenParsingException, es posible que debas actualizar la versión de la biblioteca de Acceder con Google.

  7. Detecta cualquier tipo de credencial personalizada no reconocido.

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) {

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

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

    // GoogleIdToken credential
    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")
    }
  }
}

Activa un flujo de botones de Acceder con Google

Para activar el flujo del botón de Acceder con Google, usa GetSignInWithGoogleOption en lugar de GetGoogleIdOption:

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder()
  .setServerClientId(WEB_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Controla el GoogleIdTokenCredential que se muestra como se describe en el siguiente ejemplo de código.

fun handleSignIn(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 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 credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

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

Una vez que crees una instancia de la solicitud de Acceso con Google, inicia el flujo de autenticación de una manera similar a la que se menciona en la sección Acceder con Google.

Habilitar el registro para usuarios nuevos (recomendado)

Acceder con Google es la forma más fácil para que los usuarios creen una cuenta nueva con tu app o servicio en pocos pasos.

Si no se encuentran credenciales guardadas (getGoogleIdOption no muestra ninguna Cuenta de Google), pídele al usuario que se registre. Primero, verifica si setFilterByAuthorizedAccounts(true) para ver si existe alguna cuenta usada con anterioridad. Si no se encuentra ninguna, pídele al usuario que se registre con su Cuenta de Google a través de setFilterByAuthorizedAccounts(false).

Ejemplo:

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

Una vez que crees una instancia de la solicitud de registro de Google, inicia el flujo de autenticación. Si los usuarios no desean registrarse en Google, considera usar los servicios de autocompletado o las llaves de acceso para crear cuentas.

Controla el cierre de sesión

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.

Un proveedor de credenciales puede haber almacenado una sesión de credenciales activa y usarla a fin de limitar las opciones de acceso para futuras llamadas de credenciales get. Por ejemplo, puede priorizar la credencial activa sobre cualquier otra credencial disponible. Cuando el usuario salga de tu app de forma explícita y para obtener las opciones de acceso integrales la próxima vez, debes llamar a esta API para permitir que el proveedor borre cualquier sesión de credenciales almacenada.