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

Hoja inferior habilitada para el Administrador de credenciales que muestra varias identidades para seleccionar.
Figura 1: Apariencia del diálogo de la hoja inferior de Acceder con Google después de la integración con la API de Credential Manager.

En este documento, se explica cómo migrar el diálogo de la hoja inferior de Acceder con Google de Google Identity Services (GIS) a la API de Credentials Manager con la biblioteca auxiliar de ID de Google.

Una app que usa la API de Credential Manager está configurada para presentar al usuario final una interfaz de usuario de Android coherente que le permite seleccionar una opción de una lista de opciones de acceso guardadas, incluidas las cuentas habilitadas para llaves de acceso. Esta es la API de Android recomendada para consolidar diferentes tipos y proveedores de credenciales. A partir de Android 14, los usuarios también pueden aprovechar los administradores de contraseñas de terceros con la API de Credential Manager.

Cómo declarar dependencias

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

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

Sigue las instrucciones para configurar tu proyecto de la Consola de APIs de Google. Reemplaza la guía para incluir dependencias con las instrucciones mencionadas anteriormente.

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.

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();

Primero, debes llamar a la API con el parámetro setFilterByAuthorizedAccounts configurado como true. Si no hay credenciales disponibles, vuelve a llamar a la API y configura setFilterByAuthorizedAccounts como false.

Si quieres que los usuarios accedan automáticamente cuando eso sea posible, habilita la función con setAutoSelectEnabled en la solicitud GetGoogleIdOption. El acceso automático es posible cuando se cumplen los siguientes criterios:

  • El usuario tiene exactamente una credencial guardada para tu app. Es decir, una contraseña guardada o una Cuenta de Google guardada.
  • El usuario no inhabilitó el acceso automático en la configuración de su Cuenta de Google.

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

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();

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 elemento 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, valídalo 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.

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ón de Acceder con Google

El botón de Acceder con Google es compatible con el Administrador de credenciales con la biblioteca auxiliar de ID de Google más reciente. Para activar el flujo del botón de Acceder con Google, usa GetSignInWithGoogleOption en lugar de GetGoogleIdOption y controla el GoogleIdTokenCredential que se muestra igual que antes.

Registrarse con Google

Si no se muestran resultados después de configurar setFilterByAuthorizedAccounts como true mientras se crea una instancia de una solicitud de GetGoogleIdOption y se pasa a GetCredentialsRequest, significa que no hay cuentas autorizadas para el acceso. En este punto, debes configurar setFilterByAuthorizedAccounts(false) y llamar a Registrarse con 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();

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

Controla la salida

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 y restablecer el estado interno de acceso.