Setup reCAPTCHA v2 using ReactJS + Node.js

If you need to protect your website against unwanted requests sent by bots, one of the easiest way is using captcha. However, implementing captcha by yourself is not easy and takes a lot of time. To quickly implement  captcha, it's better to use a third-party library or service. One of the most popular and free captcha services is Google reCAPTCHA. In this tutorial, I'll show you how to setting up Google reCAPTCHA v2 in ReactJS and how to handle the request on the back-end side using Node.js. I assume you've already familiar with React

1. Sign up for API key pair

In order to use reCAPTCHA, first you need to sign up to generate API key. Open the admin page of reCAPTCHA and go to Register a new site section, then fill in the Label field and choose reCAPTCHA v2. On the Domains field, enter all domains allowed to use the reCAPTCHA. You can enter multiple domains. If you are testing on localhost, it must be added on the list as well. Then tick the checbox to accept the terms of service and click on Register.

Google reCAPTCHA register 

If the registartion is successful, you'll be redirected to a new page containing site key and secret key. You'll need those values for using reCAPTCHA on your site.

Google reCAPTCHA Keys

2. ReactJS Code

In this tutorial, we use react-google-recaptcha module. First, you need to add the component on the dependency of package.json

  "react-google-recaptcha": "~0.11.1"

Then run npm install in order to install that module. In the component container, you need to import the module.

  import ReCAPTCHA from 'react-google-recaptcha'

Inside the render function, add this component.

  <ReCAPTCHA
    ref={(el) => { this.recaptcha = el; }}
    sitekey="AAbbCCddEEffGGhhIIjjKKllMMnnOOppQQr-SStt"
onChange={this.handleCaptchaResponseChange} />

As we add ref property, it's possible to access the reCAPTCHA component using this.recaptcha.

Every time a user has passed reCAPTCHA test, Google will generate a new response. We need to add onChange property, which is a function, used to update the value of reCAPTCHA response which will be sent to the server. So we need a function that handles the value change.

  handleCaptchaResponseChange(response) {
    this.setState({
      recaptchaResponse: response,
    });
  }

Don't forget to bind the function in the constructor

  this.handleCaptchaResponseChange = this.handleCaptchaResponseChange.bind(this);

Sometimes you may need to reset the captcha. For example,after the user presses the submit button, you want the user to be verified by reCAPTCHA again. If you need to do so, add the following inside function that handle the event.

  this.recaptcha.reset();

Then, the obtained reCAPTCHA response must be included in the request to the server, usually in request body.

3. Back-end Code (Node.js)

To check whether or not a request has passed reCAPTCHA test, we need to check it on the back-end. First we add these variables in .env. Don't forget to load the .env in your code.

  RECAPTCHA_SKIP_ENABLED=false
  RECAPTCHA_SITE_KEY=xxx
  RECAPTCHA_SECRET_KEY=xxx

Replace the value of RECAPTCHA_SITE_KEY and RECAPTCHA_SECRET_KEY with the one you got on step 1.

Then, we create a helper for verifying reCAPTCHA.

helpers/recaptcha.js

  const Bluebird = require('bluebird');
  const Recaptcha = require('recaptcha-v2').Recaptcha;

  /**
   * Verify ReCaptcha
   * @param {Object} recaptchaData
   * @returns {Promise}
   */
  exports.verifyRecaptcha = (recaptchaData) => {
    if (process.env.RECAPTCHA_SKIP_ENABLED === 'true') { // For development purpose only, you need to add SKIP_ENABLED in .env
      return Bluebird.resolve();
    }

    return new Bluebird((resolve, reject) => {
      const recaptcha = new Recaptcha(process.env.RECAPTCHA_SITE_KEY, process.env.RECAPTCHA_SECRET_KEY, recaptchaData);

      recaptcha.verify((success) => {
        if (success) {
          return resolve();
        }

  reject(new Error());
      });
    });
  };

Afterwards, call the helper in the route controller.

  const recaptchaHelpers = require('../helpers/recaptcha');

  router.post('/something', (req, res, next) => {
    const recaptchaData = {
      remoteip: req.connection.remoteAddress,
      response: _.get(req.body, 'recaptchaResponse'),
      secret: process.env.RECAPTCHA_SECRET_KEY,
    };

    return recaptchaHelpers.verifyRecaptcha(recaptchaData)
      .then(() => {
        // Process the request
      });
  });

If captcha verification failed, you'll need to handle it in catch block. Otherwise, it should continue to process the request.

Now, you should be able to use reCAPTCHA v2 with ReactJS front-end and Node.js back-end