Autenticación de usuarios segura

Para proteger tu sistema de autenticación en Android, procura alejarte de un modelo basado en contraseñas, en especial para las cuentas sensibles, como las cuentas bancarias y de correo electrónico de tus usuarios. Recuerda que es posible que algunas apps que instalen tus usuarios no tengan las mejores intenciones y que intenten suplantar a tus usuarios.

Tampoco des por sentado que solo los usuarios autorizados usarán el dispositivo. El robo de teléfonos es un problema común, y los atacantes apuntan a dispositivos desbloqueados para aprovechar los datos del usuario o las apps financieras directamente. Sugerimos que todas las apps sensibles implementen un tiempo de espera de autenticación razonable (¿15 minutos) con la verificación biométrica y que requieran autenticación adicional antes de que se realicen acciones sensibles, como transferencias monetarias.

Diálogo de autenticación biométrica

La biblioteca de datos biométricos ofrece un conjunto de funciones para mostrar un mensaje que solicita autenticación biométrica, como el reconocimiento facial o de huella dactilar. Sin embargo, los mensajes biométricos se pueden configurar para recurrir al LSKF, que tiene riesgos conocidos de navegación en los hombros. En el caso de las apps sensibles, te recomendamos que no tengas datos biométricos que recurran al PIN y, después de agotar los reintentos biométricos, los usuarios pueden esperar o volver a acceder con la contraseña o restablecer la cuenta. El restablecimiento de la cuenta debe requerir factores a los que no se pueda acceder fácilmente en el dispositivo (práctica recomendada a continuación).

Cómo ayuda a mitigar el fraude y el robo de llamadas telefónicas

Un caso de uso particular que puede ser útil para evitar fraudes es solicitar una autenticación biométrica dentro de tu app antes de una transacción. Cuando los usuarios deseen realizar una transacción financiera, se mostrará el diálogo biométrico para verificar que realmente sea el usuario previsto quien realiza la transacción. Esta práctica recomendada protegería contra un atacante que roba un dispositivo independientemente de que este conozca o no el LSKF, ya que deberá sondear que es el propietario del dispositivo.

Para obtener niveles de seguridad adicionales, recomendamos que los desarrolladores de apps soliciten la autenticación biométrica de clase 3 y usen CryptoObject para transacciones bancarias y financieras.

Implementación

  1. Asegúrate de incluir la biblioteca androidx.biometric.
  2. Incluye el diálogo de acceso biométrico en la actividad o el fragmento que contiene la lógica que deseas que se autentique el usuario.

Kotlin


private var executor: Executor? = null
private var biometricPrompt: BiometricPrompt? = null
private var promptInfo: BiometricPrompt.PromptInfo? = null

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_login)
  executor = ContextCompat.getMainExecutor(this)
  biometricPrompt = BiometricPrompt(this@MainActivity,
    executor, object : AuthenticationCallback() {
      fun onAuthenticationError(
        errorCode: Int,
        @NonNull errString: CharSequence
      ) {
        super.onAuthenticationError(errorCode, errString)
        Toast.makeText(
          getApplicationContext(),
          "Authentication error: $errString", Toast.LENGTH_SHORT
        )
          .show()
      }

      fun onAuthenticationSucceeded(
        @NonNull result: BiometricPrompt.AuthenticationResult?
      ) {
        super.onAuthenticationSucceeded(result)
        Toast.makeText(
          getApplicationContext(),
          "Authentication succeeded!", Toast.LENGTH_SHORT
        ).show()
      }

      fun onAuthenticationFailed() {
        super.onAuthenticationFailed()
        Toast.makeText(
          getApplicationContext(), "Authentication failed",
          Toast.LENGTH_SHORT
        )
          .show()
      }
    })
  promptInfo = Builder()
    .setTitle("Biometric login for my app")
    .setSubtitle("Log in using your biometric credential")
    .setNegativeButtonText("Use account password")
    .build()

  // Prompt appears when user clicks "Log in".
  // Consider integrating with the keystore to unlock cryptographic operations,
  // if needed by your app.
  val biometricLoginButton: Button = findViewById(R.id.biometric_login)
  biometricLoginButton.setOnClickListener { view ->
    biometricPrompt.authenticate(
      promptInfo
    )
  }
}

Java


private Executor executor;
private BiometricPrompt biometricPrompt;
private BiometricPrompt.PromptInfo promptInfo;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    executor = ContextCompat.getMainExecutor(this);
    biometricPrompt = new BiometricPrompt(MainActivity.this,
            executor, new BiometricPrompt.AuthenticationCallback() {
        @Override
        public void onAuthenticationError(int errorCode,
                @NonNull CharSequence errString) {
            super.onAuthenticationError(errorCode, errString);
            Toast.makeText(getApplicationContext(),
                "Authentication error: " + errString, Toast.LENGTH_SHORT)
                .show();
        }

        @Override
        public void onAuthenticationSucceeded(
                @NonNull BiometricPrompt.AuthenticationResult result) {
            super.onAuthenticationSucceeded(result);
            Toast.makeText(getApplicationContext(),
                "Authentication succeeded!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAuthenticationFailed() {
            super.onAuthenticationFailed();
            Toast.makeText(getApplicationContext(), "Authentication failed",
                Toast.LENGTH_SHORT)
                .show();
        }
    });

    promptInfo = new BiometricPrompt.PromptInfo.Builder()
            .setTitle("Biometric login for my app")
            .setSubtitle("Log in using your biometric credential")
            .setNegativeButtonText("Use account password")
            .build();

    // Prompt appears when the user clicks "Log in".
    // Consider integrating with the keystore to unlock cryptographic operations,
    // if needed by your app.
    Button biometricLoginButton = findViewById(R.id.biometric_login);
    biometricLoginButton.setOnClickListener(view -> {
            biometricPrompt.authenticate(promptInfo);
    });
}

Prácticas recomendadas

Te recomendamos que comiences con el codelab para obtener más información sobre los datos biométricos.

Según tus casos de uso, puedes implementar el diálogo con o sin una acción explícita del usuario. Para evitar fraudes, te recomendamos que agregues el diálogo biométrico con una acción explícita del usuario para cada transacción. Entendemos que agregar autenticación puede generar inconvenientes en la UX, pero debido a la naturaleza de la información que se maneja en una transacción bancaria y que la autenticación biométrica es más fluida que con otros métodos de autenticación, creemos que es necesario agregar este nivel de navegación.

Obtén más información sobre la autenticación biométrica.

Llaves de acceso

Las llaves de acceso son una alternativa más segura y sencilla a las contraseñas. Las llaves de acceso usan criptografía de clave pública para permitir que los usuarios accedan a apps y sitios web con el mecanismo de bloqueo de pantalla de su dispositivo, como la huella dactilar o el reconocimiento facial. Esto evita que el usuario tenga que recordar y administrar contraseñas, y proporciona una seguridad mucho mayor.

Las llaves de acceso pueden cumplir con los requisitos de autenticación de varios factores en un solo paso, ya que reemplazan una contraseña y los códigos OTP para ofrecer una protección sólida contra ataques de suplantación de identidad (phishing) y evitar que los usuarios tengan que lidiar con los SMS o las contraseñas de un solo uso basadas en la app. Dado que las llaves de acceso están estandarizadas, una sola implementación permite una experiencia sin contraseña en todos los dispositivos, navegadores y sistemas operativos de los usuarios.

En Android, las llaves de acceso son compatibles con la biblioteca de Jetpack Credential Manager, que unifica los métodos de autenticación principales, incluidas las llaves de acceso, las contraseñas y el acceso federado (como Acceder con Google).

Cómo ayuda esto a mitigar el fraude

Las llaves de acceso te protegen de los ataques de suplantación de identidad (phishing), ya que solo funcionan en tus apps y sitios web registrados.

El componente principal de una llave de acceso es una clave privada criptográfica. Por lo general, esta clave privada reside solo en tus dispositivos, como laptops o teléfonos celulares, y la sincronizan los proveedores de credenciales (también conocidos como administradores de contraseñas), como el Administrador de contraseñas de Google. El servicio en línea solo guarda la clave pública correspondiente cuando se crea una llave de acceso. Durante el acceso, el servicio usa la clave privada para firmar un desafío a partir de la clave pública. Esto solo puede originarse en uno de tus dispositivos. Además, para que esto ocurra, debes desbloquear tu dispositivo o almacenamiento de credenciales, lo que evita los accesos no autorizados (por ejemplo, desde un teléfono robado).

Para evitar el acceso no autorizado en el caso de un dispositivo robado y desbloqueado, las llaves de acceso deben combinarse con un período de tiempo de espera de autenticación razonable. Un atacante que roba un dispositivo no debería poder usar una aplicación solo porque el usuario anterior ya había accedido. En cambio, las credenciales deben vencer a intervalos regulares (por ejemplo, cada 15 minutos) y se debe exigir a los usuarios que verifiquen su identidad a través de la reautenticación con el bloqueo de pantalla.

Si te roban el teléfono, las llaves de acceso te protegen porque los ladrones no pueden robar las contraseñas para usarlas en otros dispositivos. Las llaves de acceso son específicas del dispositivo. Si usas el Administrador de contraseñas de Google y te roban el teléfono, puedes acceder a tu Cuenta de Google desde otro dispositivo (como una computadora) y salir de forma remota del teléfono robado. Esto hace que no se pueda usar el Administrador de contraseñas de Google en el teléfono robado, incluidas las llaves de acceso guardadas.

En el peor de los casos, si no se recupera el dispositivo robado, el proveedor de credenciales que creó y sincronizó las llaves de acceso sincroniza las llaves de acceso con el dispositivo nuevo. Por ejemplo, el usuario puede haber elegido el Administrador de contraseñas de Google para crear la llave de acceso y puede acceder a ella en un dispositivo nuevo si vuelve a acceder a su Cuenta de Google y proporciona el bloqueo de pantalla del dispositivo anterior.

Obtén más información en el artículo Seguridad de las llaves de acceso en el Administrador de contraseñas de Google.

Implementación

Las llaves de acceso son compatibles con dispositivos que ejecutan Android 9 (nivel de API 28) o versiones posteriores. Las contraseñas y Acceder con Google son compatibles a partir de Android 4.4. Para comenzar a usar las llaves de acceso, sigue estos pasos:

  1. Sigue el codelab del Administrador de credenciales para comprender inicialmente cómo implementar las llaves de acceso.
  2. Revisa los lineamientos de diseño de la experiencia del usuario de las llaves de acceso. En este documento, se muestra qué flujos se recomiendan para tu caso de uso.
  3. Estudia el Administrador de credenciales siguiendo la guía.
  4. Planifica la implementación del Administrador de credenciales y llaves de acceso para tu app. Planifica cómo agregar compatibilidad con Vínculos de recursos digitales.

Consulta nuestra documentación para desarrolladores y obtén más detalles para crear, registrar y autenticarte con llaves de acceso.

Restablecimiento seguro de la cuenta

Un atacante no autorizado con acceso a un dispositivo desbloqueado (como cuando se roba un teléfono) intentará acceder a apps sensibles, en especial a apps bancarias o de dinero en efectivo. Si la app implementa la verificación biométrica, el atacante intentará restablecer la cuenta para acceder. Es fundamental que el flujo de restablecimiento de cuentas no dependa solo de información a la que se pueda acceder fácilmente en el dispositivo, como los vínculos de restablecimiento de OTP por correo electrónico o SMS.

A continuación, se incluyen prácticas recomendadas comunes que puedes incorporar en el flujo de restablecimiento de tu app:

  • El reconocimiento facial, además de la OTP
  • Preguntas de seguridad
  • Factor de conocimiento (como el apellido de soltera de la madre, la ciudad de nacimiento o la canción favorita)
  • Verificación de ID

API de SMS Retriever

La API de SMS Retriever te permite realizar una verificación del usuario basada en SMS en tu app para Android automáticamente. De esa manera, no será necesario que el usuario tenga que escribir códigos de verificación de forma manual. Además, esta API no le solicita al usuario permisos adicionales de la app potencialmente peligrosos, como RECEIVE_SMS o READ_SMS. Sin embargo, SMS no debe usarse como la única verificación del usuario para proteger el dispositivo contra accesos locales no autorizados.

Cómo ayuda esto a mitigar el fraude

Algunos usuarios usan códigos SMS como único factor de autenticación, lo que proporciona un punto de entrada fácil para el fraude.

La API de SMS Retriever permite que la app recupere directamente el código SMS sin interacción del usuario y puede proporcionar un nivel de protección contra el fraude.

Implementación

La implementación de la API de SMS Retriever tiene dos partes: Android y Server.

Android: (guía)

  1. Obtén el número de teléfono del usuario.
  2. Inicia el cliente de SMS retriever.
  3. Envía el número de teléfono a tu servidor.
  4. Recibir mensajes de verificación
  5. Envía la OTP a tu servidor.

Servidor: (guía).

  1. Crea un mensaje de verificación.
  2. Envía el mensaje de verificación por SMS.
  3. Verifica la OTP cuando se devuelva.

Prácticas recomendadas

Una vez que se integra la app y se verifica el número de teléfono del usuario con la API de SMS Retriever, este intenta obtener la OTP. Si tiene éxito, eso es un fuerte indicador de que el SMS se recibió automáticamente en el dispositivo. Si no tiene éxito y el usuario necesita escribir la OTP de forma manual, puede ser una señal de advertencia de que el usuario podría estar experimentando un fraude.

SMS no debe usarse como el único mecanismo de verificación del usuario, ya que deja lugar a ataques locales, como un atacante que roba un dispositivo desbloqueado o ataques de clonación de SIM. Se recomienda usar datos biométricos siempre que sea posible. En los dispositivos que no cuentan con sensores biométricos, la autenticación del usuario debe basarse en al menos un factor que no se obtiene fácilmente del dispositivo actual.

Más información

Para obtener más información sobre las prácticas recomendadas, consulta los siguientes recursos: