API de reCAPTCHA de SafetyNet

El servicio SafetyNet incluye una API de reCAPTCHA que puedes usar para proteger tu app contra el tráfico malicioso.

reCAPTCHA es un servicio gratuito que utiliza un motor de análisis de riesgos avanzado para proteger tu app contra el spam y otras acciones abusivas. Si el servicio sospecha que el usuario que está interactuando con tu app podría ser un bot y no una persona, mostrará un CAPTCHA que se deberá resolver para seguir ejecutando la app.

En este documento, se explica cómo integrar la API de reCAPTCHA de SafetyNet en tu app.

Condiciones del Servicio adicionales

Al acceder a la API de reCAPTCHA o usarla, aceptas las Condiciones del Servicio de API de Google y estas Condiciones adicionales. Lee y comprende todos los términos y las políticas aplicables antes de acceder a las API.

Condiciones del Servicio de reCAPTCHA

Reconoces y comprendes que la API de reCAPTCHA funciona mediante la recopilación de información de hardware y software, como datos de dispositivos y apps, y resultados de verificaciones de integridad, y que envía esos datos a Google para su análisis. Según el Artículo 3(d) de las Condiciones del Servicio de las API de Google, aceptas que, si utilizas las API, eres responsable de brindar avisos o el consentimiento necesario para la recopilación y el uso compartido de estos datos con Google.

Cómo registrar un par de claves de reCAPTCHA

Si quieres registrar un par de claves para usar con la API de reCAPTCHA de SafetyNet, ve al sitio de registro de reCAPTCHA para Android y, luego, completa la siguiente secuencia de pasos:

  1. En el formulario que aparece, proporciona la siguiente información:

    • Label: Una etiqueta única para tu clave. Por lo general, incluye el nombre de tu organización o empresa.
    • Nombres de los paquetes: proporciona el nombre del paquete de cada app que utilice esta clave de API. Para que una app use la API, el nombre del paquete que ingreses debe ser una coincidencia exacta del nombre del paquete para esa app. Ingresa el nombre de cada paquete en su propia línea.
    • Enviar alertas a los propietarios: marca esta casilla de verificación si deseas recibir correos electrónicos sobre la API de reCAPTCHA.
  2. Marca la casilla de verificación Aceptar las Condiciones del Servicio de reCAPTCHA y, luego, haz clic en Registrarse.

  3. En la sección Cómo agregar reCAPTCHA a tu app de la página que aparece a continuación, se muestran las claves pública y privada en Clave de sitio y Clave secreta, respectivamente. Usa la clave del sitio para enviar la solicitud de verificación y usa la clave secreta a fin de validar el token de respuesta del usuario.

Cómo agregar una dependencia de la API de SafetyNet

Antes de usar la API de reCAPTCHA, debes agregar la API de SafetyNet a tu proyecto. Si usas Android Studio y deseas compilar de manera selectiva esta API en tus dependencias de Gradle, debes incluir la regla de compilación que se muestra en el siguiente fragmento de código:

    apply plugin: 'com.android.application'
    ...
    dependencies {
        compile 'com.google.android.gms:play-services-safetynet:17.0.0'
    }
    

Para obtener más información, consulta Cómo configurar los Servicios de Google Play.

Cómo usar la API de reCAPTCHA

En esta sección, se describe cómo llamar a la API de reCAPTCHA para enviar una solicitud de verificación de CAPTCHA y recibir el token de respuesta del usuario.

Cómo enviar la solicitud de verificación

Para invocar la API de reCAPTCHA de SafetyNet, llama al método verifyWithRecaptcha(). Por lo general, se activa ese método cada vez que el usuario selecciona un elemento de la IU, como un botón, en tu actividad.

Cuando uses el método verifyWithRecaptcha() en tu app, deberás hacer lo siguiente:

En el siguiente fragmento de código, se muestra cómo invocar este método:

Kotlin

    fun onClick(view: View) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
                .addOnSuccessListener(this as Executor, OnSuccessListener { response ->
                    // Indicates communication with reCAPTCHA service was
                    // successful.
                    val userResponseToken = response.tokenResult
                    if (response.tokenResult?.isNotEmpty() == true) {
                        // Validate the user response token using the
                        // reCAPTCHA siteverify API.
                    }
                })
                .addOnFailureListener(this as Executor, OnFailureListener { e ->
                    if (e is ApiException) {
                        // An error occurred when communicating with the
                        // reCAPTCHA service. Refer to the status code to
                        // handle the error appropriately.
                        Log.d(TAG, "Error: ${CommonStatusCodes.getStatusCodeString(e.statusCode)}")
                    } else {
                        // A different, unknown type of error occurred.
                        Log.d(TAG, "Error: ${e.message}")
                    }
                })
    }
    

Java

    public void onClick(View v) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
            .addOnSuccessListener((Executor) this,
                new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
                    @Override
                    public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
                        // Indicates communication with reCAPTCHA service was
                        // successful.
                        String userResponseToken = response.getTokenResult();
                        if (!userResponseToken.isEmpty()) {
                            // Validate the user response token using the
                            // reCAPTCHA siteverify API.
                        }
                    }
            })
            .addOnFailureListener((Executor) this, new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        if (e instanceof ApiException) {
                            // An error occurred when communicating with the
                            // reCAPTCHA service. Refer to the status code to
                            // handle the error appropriately.
                            ApiException apiException = (ApiException) e;
                            int statusCode = apiException.getStatusCode();
                            Log.d(TAG, "Error: " + CommonStatusCodes
                                    .getStatusCodeString(statusCode));
                        } else {
                            // A different, unknown type of error occurred.
                            Log.d(TAG, "Error: " + e.getMessage());
                        }
                    }
            });
    }
    

Cómo validar el token de respuesta del usuario

Cuando la API de reCAPTCHA ejecuta el método onSuccess(), significa que el usuario completó correctamente el desafío de CAPTCHA. Sin embargo, este método solo indica que el usuario resolvió el CAPTCHA de forma correcta. Aún debes validar el token de respuesta del usuario desde el servidor de backend.

Para aprender a validar el token de respuesta del usuario, consulta Cómo verificar la respuesta del usuario.

Cómo controlar los errores de comunicación

Si la app no se puede comunicar con el servicio de reCAPTCHA correctamente, es posible que la API haya detectado un error. Deberás agregar lógica en tu app para resolver el error. Además, cuando se produce el error, tu app debe mostrar un mensaje al usuario en el que se explique por qué no puede terminar de procesar su respuesta de CAPTCHA.

En la siguiente lista, se muestran los códigos de estado de los errores más comunes de la API:

RECAPTCHA_INVALID_SITEKEY

No es válida la clave del sitio. Asegúrate de haber registrado correctamente una clave de API y de haber copiado la clave del sitio como parámetro cuando llamaste a la API.

Valor constante: 12007

RECAPTCHA_INVALID_KEYTYPE

No es válido el tipo de clave de sitio. Ve al sitio de registro de reCAPTCHA y crea una nueva clave.

Valor constante: 12008

RECAPTCHA_INVALID_PACKAGE_NAME

El nombre del paquete de la aplicación de llamada no coincide con ninguno de los nombres que asociaste con la clave del sitio. Agrega el nombre del paquete de la app que realiza la llamada a la clave del sitio en la Consola del administrador de reCAPTCHA o desactiva la validación del nombre del paquete para la clave del sitio.

Valor constante: 12013

UNSUPPORTED_SDK_VERSION

La API no es compatible con la versión del SDK de Android del dispositivo. Actualiza a una nueva versión del SDK de Android y, luego, intenta comunicarte nuevamente con la API.

Valor constante: 12006

TIMEOUT

Se agotó el tiempo de espera de la sesión porque la API esperó una respuesta, ya sea porque el usuario no interactuó con el CAPTCHA o porque se agotó el tiempo del propio proceso de carga del CAPTCHA. Espera a que el usuario vuelva a invocar la API. Mientras tanto, informa al usuario que debe completar el CAPTCHA para seguir usando tu app.

Valor constante: 15

NETWORK_ERROR

No hay conexión a Internet. Después de garantizar la conectividad, intenta volver a comunicarte con la API.

Valor constante: 7

ERROR

La operación detectó una falla general.

Valor constante: 13

Para obtener más detalles sobre los códigos de estado que puede mostrar la API de reCAPTCHA, consulta la referencia SafetyNetStatusCodes.