How To Integrate Google's reCaptcha Validation In Android

In this article, we will learn what is reCaptcha for Android and how to integrate the same to Android Apps.

Google’s reCaptcha

Introduction

In this article, we will learn what reCaptcha is for Android and how to integrate the same to Android apps.

This option is provided by Google. Google’s reCaptcha API protects your app from malicious traffic and it is integrated with your Android apps using SafetyNet API. The service is free to use and it will show a Captcha to be solved if the engine suspects user interaction to be a bot instead of human.

How it works

The following points explain the simple flow of reCaptcha in Android with SafetyNet API.

  1. We need to get site key pair from SafetyNet by registering our app.
  2. We will get Site Key and get user response token from SafetyNet server using SafetyNet API in Android.
  3. Then, validate the token with the SafetyNet server using the curl commands and site key.

Registering your App with SafetyNet Server

  1. Open reCaptcha site from the following link.

    https://www.google.com/recaptcha/admin#list
  1. Go to Register New Site section and select Option reCAPTCHA Android. The following figure explains the same.

    Google’s reCaptcha
    Figure 1
  1. Then, add your Package Name in Package Names Section as shown in the above figure. We can add multiple apps and each can be separated by hitting Enter or new line.

  2. Check or select the "Accept Terms" Checkbox and click Register button. The following figure shows the same.

    Google’s reCaptcha
    Figure 2
  1. Then, you will get the site key and secret key from SafetyNet API Server and it as well as shows client and server-side integration code snippets. The following figures show the same.

    Google’s reCaptcha
    Figure 3

    Google’s reCaptcha
    Figure 4

I have divided this implementation into 4 steps, as shown in the following.

  • Step 1: Creating New Project with Android Studio
  • Step 2: Setting up the library and AndroidManifest for the project.
  • Step 3: Implementation of the SafetyNet API.
  • Step 4: Captcha Response Token Validation.

 

Step 1 - Creating New Project with Android Studio

  1. Open Android Studio and select "Create New Project".
  2. Name the project as your wish and select your activity template.

    Google’s reCaptcha

  3. Click “Finish” button to create a new project in Android Studio.

Step 2 - Setting up the library and AndroidManifest for the project

  1. Add Google Play service library dependency in your app level build.gradle file. Here, I used the following dependency. You can change as per your Android SDK.
    1. implementation 'com.google.android.gms:play-services-safetynet:15.0.1'  
    2. implementation 'com.android.volley:volley:1.1.0’  
  2. Then, click “Sync Now” to add the library.

  3. Now, open your App Manifest file (AndroidManifest.xml) and add the following permission.
    1. <uses-permission android:name="android.permission.INTERNET" />  
  1. SafetyNet library is used to create the Captcha Validation in Android.

Volley Library is an HTTP Networking Library used here for validating Captcha Response.

Step 3 - Implementation of SafetyNet API:

  1. Add the following to get the Captcha Token from SafetyNet Server.
    1. SafetyNet.getClient(this).verifyWithRecaptcha(SITE_KEY)  
    2.                 .addOnSuccessListener(thisnew OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {  
    3.                     @Override  
    4.                     public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {  
    5.                         if (!response.getTokenResult().isEmpty()) {  
    6.                             handleCaptchaResult(response.getTokenResult());  
    7.                         }  
    8.                     }  
    9.                 })  
    10.                 .addOnFailureListener(thisnew OnFailureListener() {  
    11.                     @Override  
    12.                     public void onFailure(@NonNull Exception e) {  
    13.                         if (e instanceof ApiException) {  
    14.                             ApiException apiException = (ApiException) e;  
    15.                             Log.d(TAG, "Error message: " +  
    16.                                     CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));  
    17.                         } else {  
    18.                             Log.d(TAG, "Unknown type of error: " + e.getMessage());  
    19.                         }  
    20.                     }  
    21.                 });  
  1. Replace “SITE_KEY” with your appropriate “Site Key” get from SafetyNet API while registering app.
  2. The API will check the Server and it has a separate callbacks from success and failure.
  3. At Success, we will get Captcha Response Token which will be used to validate the user interaction is made by a bot or real human.
  4. We will discuss how to validate the token with SafetyNet API Server in next step.

Step 4 - Captcha Response Token Validation

  1. We have to verify the token getting from the server using the secret key.
  2. It can achieve by using the following.
    • API Link - https://www.google.com/recaptcha/api/siteverify
    • Method - POST
    • Params – secret, response (We have to pass the “SECRET_KEY” and “TOKEN” respectively)
  1. Volley Library is used to verify the same.
    1. String url = "https://www.google.com/recaptcha/api/siteverify";  
    2.     StringRequest request = new StringRequest(Request.Method.POST, url,  
    3.             new Response.Listener<String>() {  
    4.                 @Override  
    5.                 public void onResponse(String response) {  
    6.                     try {  
    7.                         JSONObject jsonObject = new JSONObject(response);  
    8.                         if(jsonObject.getBoolean("success")){  
    9.                             tvVerify.setText("You're not a Robot");  
    10.                         }  
    11.                     } catch (Exception ex) {  
    12.                         Log.d(TAG, "Error message: " + ex.getMessage());  
    13.   
    14.                     }  
    15.                 }  
    16.             },  
    17.             new Response.ErrorListener() {  
    18.                 @Override  
    19.                 public void onErrorResponse(VolleyError error) {  
    20.                     Log.d(TAG, "Error message: " + error.getMessage());  
    21.                 }  
    22.             }) {  
    23.         @Override  
    24.         protected Map<String, String> getParams() {  
    25.             Map<String, String> params = new HashMap<>();  
    26.             params.put("secret", SITE_SECRET_KEY);  
    27.             params.put("response", responseToken);  
    28.             return params;  
    29.         }  
    30.     };  
    31.     request.setRetryPolicy(new DefaultRetryPolicy(  
    32.             50000,  
    33.             DefaultRetryPolicy.DEFAULT_MAX_RETRIES,  
    34.             DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));  
    35.     queue.add(request);  
  1. Volley has
    • RequestQueue to maintain the server calls in queue.
    • RetryPolicy to retry the server call if it is fail with TimeOut and Retry Count. We can change those values.
    • StringRequest is used for getting Response as JSON String.
    • Method.POST denotes the call as POST method.
    • Params are passed to server using Map, HashMap.
  1. The SafetyNet API provides the response respective to the parameters passed and the success is Boolean Datatype.

We can learn more about volley library in future.

Full Code

You can find the full code implementation of the API.

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {  
  2.   
  3.     Button btnVerify;  
  4.     TextView tvVerify;  
  5.     String TAG = MainActivity.class.getSimpleName();  
  6.     String SITE_KEY = " SITE_KEY";  
  7.     String SITE_SECRET_KEY = " SITE_SECRET_KEY";  
  8.     RequestQueue queue;  
  9.   
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.activity_main);  
  14.         btnVerify = findViewById(R.id.btn_verify);  
  15.         tvVerify = findViewById(R.id.tv_verify);  
  16.         btnVerify.setOnClickListener(this);  
  17.   
  18.         queue = Volley.newRequestQueue(getApplicationContext());  
  19.     }  
  20.   
  21.     @Override  
  22.     public void onClick(View view) {  
  23.         SafetyNet.getClient(this).verifyWithRecaptcha(SITE_KEY)  
  24.                 .addOnSuccessListener(thisnew OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {  
  25.                     @Override  
  26.                     public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {  
  27.                         if (!response.getTokenResult().isEmpty()) {  
  28.                             handleCaptchaResult(response.getTokenResult());  
  29.                         }  
  30.                     }  
  31.                 })  
  32.                 .addOnFailureListener(thisnew OnFailureListener() {  
  33.                     @Override  
  34.                     public void onFailure(@NonNull Exception e) {  
  35.                         if (e instanceof ApiException) {  
  36.                             ApiException apiException = (ApiException) e;  
  37.                             Log.d(TAG, "Error message: " +  
  38.                                     CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));  
  39.                         } else {  
  40.                             Log.d(TAG, "Unknown type of error: " + e.getMessage());  
  41.                         }  
  42.                     }  
  43.                 });  
  44.     }  
  45.   
  46.     void handleCaptchaResult(final String responseToken) {  
  47.         String url = "https://www.google.com/recaptcha/api/siteverify";  
  48.         StringRequest request = new StringRequest(Request.Method.POST, url,  
  49.                 new Response.Listener<String>() {  
  50.                     @Override  
  51.                     public void onResponse(String response) {  
  52.                         try {  
  53.                             JSONObject jsonObject = new JSONObject(response);  
  54.                             if(jsonObject.getBoolean("success")){  
  55.                                 tvVerify.setText("You're not a Robot");  
  56.                             }  
  57.                         } catch (Exception ex) {  
  58.                             Log.d(TAG, "Error message: " + ex.getMessage());  
  59.   
  60.                         }  
  61.                     }  
  62.                 },  
  63.                 new Response.ErrorListener() {  
  64.                     @Override  
  65.                     public void onErrorResponse(VolleyError error) {  
  66.                         Log.d(TAG, "Error message: " + error.getMessage());  
  67.                     }  
  68.                 }) {  
  69.             @Override  
  70.             protected Map<String, String> getParams() {  
  71.                 Map<String, String> params = new HashMap<>();  
  72.                 params.put("secret", SITE_SECRET_KEY);  
  73.                 params.put("response", responseToken);  
  74.                 return params;  
  75.             }  
  76.         };  
  77.         request.setRetryPolicy(new DefaultRetryPolicy(  
  78.                 50000,  
  79.                 DefaultRetryPolicy.DEFAULT_MAX_RETRIES,  
  80.                 DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));  
  81.         queue.add(request);  
  82.     }  
  83. }  

Demo

You can find the demo in YouTube.

Download Code

You can download the full source code of the article from GitHub. If you like this article, do star the repo in GitHub.