Adding Google reCAPTCHA in ReactJS

Total
0
Shares
Adding Google recaptcha in reactjs application

reCAPTCHA is a captcha system which helps in securing applications. It is owned and maintained by Google. This is a joint effort of Google and Carnegie Mellon University. In this article, we will learn how to integrate google reCAPTCHA in ReactJS applications.

With the introduction of reCAPTCHA v3, now there is no need to ask users to prove that they are humans. It automatically detects that. A score is generated which allows you to consider a visit to be genuine or spam. But this will only give score and won’t prevent users to access anything. If you feel that score is bad, then you might need to use reCAPTCHA v2 to challenge them.

Adding reCAPTCHA v3

The process of adding a reCAPTCHA starts from registering the application in Google and getting the API keys.

Registration of website

1. Visit http://www.google.com/recaptcha/admin. The registration form will look like this –

Website registration form in recaptcha

2. Fill the form with appropriate information of your website. For this website (akashmittal.com), we will fill the form like this –

Label – akashmittal.com
reCAPTCHA Type – reCAPTCHA v3
Domains – akashmittal.com

After filling the information, you should read the terms of service properly. Accept by marking the checkbox if you are okay with those terms. Also, if you want to receive alert mails on your provided email id, then you can check mark that option too.

The form will look like this now –

recaptcha registration form filled with information of akashmittal.com website

3. Submit the form now. In the next screen you will get your API keys. If you are new to this whole API business, then you need to know that these keys should be kept safe. Don’t share or display them to anybody. The key page will look like below image (I have hidden them for my safety).

Registration process is completed. Now you can go to analytics. Although there will be no analytics for now because we still need to integrate this google recaptcha into our ReactJS app.

You may also like –

Integration of reCAPTCHA in React code

First of all you should know how recaptcha interacts with your application. You call the “system” on multiple things where you want security. For example –

  • Checking authenticity of comments on posts.
  • Similarly, authenticity of product reviews.
  • Login, Registration, Purchase forms.
  • And lot more…

In all these scenarios, you will need to call the reCAPTCHA system to get the score. This score indicates how suspicious the action was. It ranges from 1.0 to 0.0 with 1 being the most genuine and 0 being the most robotic.

But you won’t get the score directly in the React app. Else you will get the token string which you will need to verify at the backend. Then you will get the score. Don’t worry, we will cover all these steps in this article. Although, if you want to learn more about token verification processes, then check out our single sign on guide.

Importing recaptcha script

Let’s start our integration. First import the below script into the index.html ([your project] / public / index.html) file of your project.

 <script src="https://www.google.com/recaptcha/api.js?render=[reCAPTCHA_site_key]"></script>

You need to replace [reCAPTCHA_site_key] with the site API key provided by reCAPTCHA and not secret key.

In my case, script import will look like this –

<script src="https://www.google.com/recaptcha/api.js?render=6LdFukIaAAAAAM-L6fAcuCBsYRpLhmeaSxoB-QnX"></script>

Why I am showing my site key to you when I was saying to keep it secret before? Because site key are not private. These are designed for frontend and hence visible to browsers, users, frameworks and everybody. It’s good to keep it safe too but any ways it’s going to be public. But keep your secret key secure and private.

If you forgot your api keys then you can access them again from settings in your reCAPTCHA dashboard. See this image –

settings on recaptcha dashboard

So, my index.html file is looking like this –

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
    <script src="https://www.google.com/recaptcha/api.js?render=6LdFukIaAAAAAM-L6fAcuCBsYRpLhmeaSxoB-QnX"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

Adding recaptcha system to forms

Next, create a form which we want to protect using reCAPTCHA v3 in app.js

import React from 'react';

function App() {
  const [name, setName] = React.useState('');
  const [age, setAge] = React.useState('');

  return (
    <div>
      <h4>This form is powered by reCAPTCHA</h4>
      <form id="demo-form">
        <input 
              type="text" 
              value={name} 
              placeholder="Full Name" 
              onChange={e => setName(e.target.value)} 
              required
        /><br />
        <input 
              type="number" 
              value={age} 
              placeholder="Age" 
              onChange={e => setAge(e.target.value)} 
              required 
        /><br />
        <button type='submit'>Submit</button>
      </form>
    </div>
  );
}

export default App;

Currently this form doesn’t have reCAPTCHA installed. It is a simple form with two fields – Name and age. The interface will appear like this –

To add reCAPTCHA in it, we have to make few changes. The submit button will be replaced with this code –

<button 
    data-action='submit'
    onClick={e => onFormSubmit(e)}
>Submit</button>

In this above code, we are setting a data attribute data-action to a value. This value could be anything you like, but keep it meaningful. Because you will get analytics in your dashboard with the identity of these names. Suppose you have 10 different forms in your website which you want to protect using reCAPTCHA, then keeping 10 different actions will help you to recognize user behavior on them separately.

Let’s code our onFormSubmit function which will be called when submit button is pressed.

function onFormSubmit(e) {
  e.preventDefault();
  window.grecaptcha.ready(function() {
    window.grecaptcha.execute('[reCAPTCHA_site_key]', {action: 'submit'}).then(function(token) {
      // Send form value as well as token to the server
    });
  });
}

    Tweet this code to help others

Again replace [reCAPTCHA_site_key] with your site key. Also look that we are passing {action: 'submit'} which indicates the library to check the values of form with data-action="submit".

Our updated code will be like this –

import React from 'react';
import './App.css';

function App() {
  const [name, setName] = React.useState('');
  const [age, setAge] = React.useState('');


  function onFormSubmit(e) {
    e.preventDefault();
    window.grecaptcha.ready(function() {
      window.grecaptcha.execute('6LdFukIaAAAAAM-L6fAcuCBsYRpLhmeaSxoB-QnX', {action: 'submit'}).then(function(token) {
        // Send form value as well as token to the server
      });
    });
  }
  return (
    <div className="App">
      <h4>This form is powered by reCAPTCHA</h4>
      <form id="demo-form">
        <input 
              type="text" 
              value={name} 
              placeholder="Full Name" 
              onChange={e => setName(e.target.value)} 
              required
        /><br />
        <input 
              type="number" 
              value={age} 
              placeholder="Age" 
              onChange={e => setAge(e.target.value)} 
              required 
        /><br />
        <button 
          onClick={e => onFormSubmit(e)}
          data-action='submit'>Submit</button>
      </form>
    </div>
  );
}

export default App;

Getting score from server

As I said before, Reactjs app will only get the token sent by google recaptcha. We can’t determine any useful information from this token itself, until and unless we get the score.

Getting the score is easy. We just have to make an HTTP post request to https://www.google.com/recaptcha/api/siteverify with token and our secret api key. It respond back with either score or error codes.

The CURL request will be –

curl -XPOST -H “Content-type: application/json” -d ‘{“secret”:”[YOUR SECRET KEY]”, “response”:”[TOKEN]”}’ ‘https://www.google.com/recaptcha/api/siteverify’

The response will be JSON –

{
  "success": true|false,      // whether this request was a valid reCAPTCHA token for your site
  "score": number,             // the score for this request (0.0 - 1.0)
  "action": string,            // the action name for this request (important to verify)
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
  "error-codes": [...]        // optional
}

Server code in PHP (Example)

If you are coding your backend in php then you can use this code for server token validation –

<?php
  $postfields = array(
                  'secret'=> 'xxxxxxxxxxxxxxxxxxxxxxxxx-xxxx',
                  'response'=> $_POST['token']
	       );
			  
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/recaptcha/api/siteverify');
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($ch, CURLOPT_POST, 1);

  curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
  $result = curl_exec($ch);

  $result = json_decode($result, true);

  if($result['success']){
	// check $result['score'] value and take action accordingly.
  } else {
	// deal with $result['error-codes']
  }
?>

Replace xxxx..xxx with your secret api key. I have not shown my api key here because it needs to be kept secret.

LIVE DEMO

If you open this page on VPN like Opera VPN, Brave VPN, Malwarebytes VPN or any other then you will see a dramatic change in score. Because traffic from VPN are generally not of high quality and their reputation are low (except Malwarebytes VPN which is a security company and hence provides high quality VPN).

So.. we reached the end of our article of adding google recaptcha in reactjs application. See you in the next post.