David Omotayo Frontend developer and indie game enthusiast.

How to implement reCAPTCHA in a React application

11 min read 3166

React Logo Over Purple Background

In this article, we’ll demonstrate how to implement reCAPTCHA v2 in a React application and how to verify user tokens in a Node.js backend.

Jump ahead:

Prerequisites

To follow along with the examples in the tutorial portion of this article, you should have a foundational knowledge of:

  • React and its concepts
  • Creating servers with Node.js and Express.js
  • HTTP requests

What is CAPTCHA?

CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) is a type of challenge-response security measure designed to differentiate between real website users and automated users, such as bots.

Many web services use CAPTCHAs to help prevent unwarranted and illicit activities such as spamming and password decryptions. CAPTCHAs require users to complete a simple test to demonstrate they are human and not a bot before giving them access to sensitive information.

What is reCAPTCHA?

There are several types of CAPTCHA systems, but the most widely used system is reCAPTCHA, a tool from Google. Luis von Ahn, the co-founder of Duolingo, created the tool back in 2007 and is being used by more than six million websites, including BBC, Bloomberg, and Facebook.

The first version of reCAPTCHA was made up of randomly generated sequences of distorted alphabetic and numeric characters and a text box.

Recaptcha
https://developers.google.com/recaptcha/old/docs/customization

To pass the test, a user needs to decypher the distorted characters and type them into the text box. Although computers are capable of creating images and generating responses, they can’t read or interpret information in the same way a person can to pass the test.

reCAPTCHA generates a response token for each request a user makes and sends it to Google’s API for verification. The API returns a score that determines if the user is human or an automated program.

reCAPTCHA currently has two working versions: v2 and v3. Although v3 is the most recent version of reCAPTCHA (released in 2018), most websites still use reCAPTCHA v2, which was released in 2014.



reCAPTCHA v2 has two variants: checkbox and invisible. The checkbox variant, which is also known as “I’m not a robot”, is the most popular. one option for this variant displays a checkbox widget that users can interact with to verify their identity.

I'm not a robot Recaptcha

The invisible variant displays a reCAPTCHA badge, indicating that the service is running in the background.

In some cases where a user’s behavior triggers suspicion, reCAPTCHA v2 will serve up a challenge that the user must pass to prove they’re not a bot.

Select All Images Recaptcha

Implementing reCAPTCHA in React

Now that we understand what reCAPTCHA is, let’s see how we can implement it in a React app. But first, we need to sign our app up for an API key in the Google reCAPTCHA console. The key pair consists of two keys: site key and secret key.

The site key invokes the reCAPTCHA service in our app. The secret key verifies the user’s response. It does this by authorizing the communication between our app’s backend and the reCAPTCHA server.

Go ahead and create your key pair here.

First, you’ll need to sign in with your Google account. Then, you’ll be redirected to the admin console. Next, you’ll fill out the registration form on the page to generate your site’s key pair.

Google Recaptcha

The registration is fairly straightforward, but for clarity, I’ll explain what each form field means and how to fill each field.

Key pair registration

Label

For the label field, provide a name to help you recognize the purpose of the key pair that you’re creating. If you have more than one key pair set up on your account, the labels will help you distinguish between them.

Type

The type selector refers to the version of reCAPTCHA that you want to use on your site. You can choose either v3 or v2. Since this tutorial will only cover v2 implementation, go ahead and choose v2 and the “I am not a robot” variant.

Domains

The domains field is where you’ll set the domain names that will work with your reCAPTCHA. You can input a valid domain name or “localhost” if your project is still in development, and click + to add the domain.

Owner

The owner field is where you can provision access to your app’s reCAPTCHA to others. By default, you’ll be the owner, but you can add more individuals by providing their Google emails.

Once you’ve completed the form fields, check the necessary boxes and click Submit.

Now you should be able to see your site key and secret key. They will look similar to the ones shown here:

Recaptcha Keys

Next, we‘ll set up a React sample project and implement reCAPTCHA using the key pairs we just created.

Setting up a sample React project

To verify a user’s input with reCAPTCHA we require a server that’ll communicate with Google’s API. So we‘ll need to keep that in mind when setting up the project.

First, create a folder. For this sample project, I will name the folder react-node-app, but you can use a different name of your choosing.

Next, open the folder in your preferred IDE and run the following command:

npm init -y

This will create a package.json file that will help us manage our dependencies and keep track of our scripts.


More great articles from LogRocket:


Go ahead and bootstrap a React app with create-react-app by typing the following command in your terminal:

npx create-react-app my-app

This command will create a my-app folder inside the react-node-app folder and will install React inside the my-app folder.

After installation, open the my-app folder and clean up the unnecessary boilerplate codes and files in the project folder, then create a Form.js component within the src folder.

Next, add the following code into the form component and import it inside the App.js main component.

const Form = () =>{

    return(
        <form>
            <label htmlFor="name">Name</label>
                <input type="text" id="name" className="input"/>
            <button>Submit</button>
        </form>
    )
}

export default Form

The above code is a simple login form with an input element and a Submit button.

Styling the form component isn’t necessary, but if you’d like to add a little flair, add the following CSS code inside the App.css file in the project folder.

.input{
  width: 295px;
  height: 30px;
  border: rgb(122, 195, 238) 2px solid;
  display: block;
  margin-bottom: 10px;
  border-radius: 3px;
}

.input:focus{
  border: none;
}

label{
  display: block;
  margin-bottom: 2px;
  font-family: 'Courier New', Courier, monospace;
}

button{
  padding: 7px;
  margin-top: 5px;
  width: 300px;
  background-color: rgb(122, 195, 238);
  border: none;
  border-radius: 4px;
}

Now, start the development server with the command npm start in the terminal.

You should see a form similar to this displayed on your browser:

Name Form

N.B., It is recommended to use a framework that has support for SSR (server-side-rendering), like Next.js or Remix, when creating something similar for production.

Installing react-google-recaptcha

The react-google-recaptcha library enables the integration of Google reCAPTCHA v2 in React. The package provides a component that simplifies the process of handling and rendering reCAPTCHA in React with the help of useful props.

To install react-google-recaptcha, type and run the following command:

npm install --save react-google-recaptcha

Adding reCAPTCHA

After installing react-google-recaptcha, head over to the form.js component file and import it, like so:

import reCAPTCHA from "react-google-recaptcha"

Now add the reCAPTCHA component to the form, just before or after the Submit button. Your placement of the component is optional, the reCAPTCHA widget will appear wherever the reCAPTCHA component is placed in the form when rendered.

<form >
            <label htmlFor="name">Name</label>
                <input type="text" id="name" className="input"/>
                <reCAPTCHA />
            <button>Submit</button>
</form>

As mentioned previously, the reCAPTCHA component accepts several props. However, the sitekey prop is the only prop we need to render the component. This prop facilitates the connection between the site key we generated earlier from the reCAPTCHA key pair and the reCAPTCHA component.

Here are other optional props of the reCAPTCHA component:

  • theme: changes the widget’s theme to light or dark
  • size: changes the size or type of CAPTCHA
  • onErrored: fires a callback function if the test returns an error
  • badge: changes the position of the reCAPTCHA badge (bottomright, bottomleft, or inline)
  • ref: used to access the component instance API
<reCAPTCHA
sitekey={process.env.REACT_APP_SITE_KEY}
/>

Here we add a sitekey prop to the reCAPTCHA component and pass it an environment variable with the reCAPTCHA site key.

To do the same in your project, create a .env file in the root folder of your project. Next, add the following code to the file:

/*.env*/
REACT_APP_SECRET_KEY = "Your secret key"
REACT_APP_SITE_KEY = "your site key"

This way, you can use your secret keys safely in your app by referencing the variable names where they’re needed.

Now, if save your code and go to the browser, a reCAPTCHA box should appear where the reCAPTCHA component is placed in your code. In this example, it appears before the submit button.

Name Captcha Form

After each verification, we need to reset the reCAPTCHA for subsequent checks. To accomplish this, we need to add a ref prop to the reCAPTCHA component.

To use the ref prop, first, import the useRef hook from React:

import React, { useRef } from 'react';

Next, store the ref value in a variable, like so:

const captchaRef = useRef(null)

Then, add the ref prop to the reCAPTCHA component and pass it the captchaRef variable:

<reCAPTCHA
sitekey={process.env.REACT_APP_SITE_KEY}
ref={captchaRef}
/>

Here’s the entire code in our Form component up to this point:

import reCAPTCHA from "react-google-recaptcha"

const Form = () =>{
    return(
            <form>
                <label htmlFor="name">Name</label>
                    <input type="text" id="name" className="input"/>
                    <reCAPTCHA
                    sitekey={process.env.REACT_APP_SITE_KEY} 
                    ref={captchaRef}
                    />
                <button>Submit</button>
            </form>
    )
}
export default Form

Now that we have a working widget, we just need to complete three steps to get reCAPTCHA functioning:

  1. Get the response token from the reCAPTCHA component
  2. Reset the reCAPTCHA component for subsequent checks
  3. Verify the response token in the backend

Getting the response token

We can also use the ref prop to get the generated token from our reCAPTCHA. All we have to do is get the value of the ref with the following code:

const token = captchaRef.current.getValue();

Resetting reCAPTCHA for subsequent checks

If we add the above code to the form component, it will actually cause an error. This is because the value of the ref is still null, since the reCAPTCHA is in an unchecked state. To solve this issue, we we’ll add an onSubmit event handler to the form with a function that encapsulates the code:

const handleSubmit = (e) =>{
        e.preventDefault();
        const token = captchaRef.current.getValue();
        captchaRef.current.reset();
    }

return(
        <form onSubmit={handleSubmit} >
            …
        </form>
    )    

In the above code, we created a handleSubmit function. Inside this function, we added the token variable for getting the response token from reCAPTCHA, as well as a code that resets the reCAPTCHA each time the form is submitted.

This way, the getValue() method will only attempt to get the ref’s value, which is the response token, when the submit button is clicked.

Now if you log the token variable to the console, check the reCAPTCHA box, and submit the form, you should see a generated response token similar to the one below in your console:

Console Under Name Captcha

Verifying the token in the Node.js backend

The token we generated in the previous section is only valid for two minutes, which means we need to verify it before it expires. To do so, we’ll need to set up our app’s backend and send the token to Google’s API to check the user’s score.

Setting up the Node.js backend

To set up a Node.js server, navigate back to the react-node-app folder, create a new folder, and name it server. Inside the server folder, create a new file and name it index.js. This file will serve as the entry point for our Node app.

Next, cd into the server folder and run the following command to install Express.js and Axios:

npm i express axios dotenv --save

Now, add the following code inside the index.js file:

const express = require("express");
const router = express.Router();
const app = express();
const cors = require('cors');
const axios = require('axios');
const dotenv = require('dotenv').config()
const port = process.env.PORT || 2000;

//enabling cors
app.use(cors());

//Parse data
app.use(express.json());
app.use(express.urlencoded({extended: true}));

//add router in express
app.use("/", router);

//POST route
router.post("/post", async (req, res) => {
//Destructuring response token from request body
    const {token} = req.body;

//sends secret key and response token to google
    await axios.post(
      `https://www.google.com/recaptcha/api/siteverify?secret=${process.env.SECRET_KEY}&response=${token}`
      );

//check response status and send back to the client-side
      if (res.status(200)) {
        res.send("Human 👨 👩");
    }else{
      res.send("Robot 🤖");
    }
});

app.listen(port, () =>{
    console.log(`server is running on ${port}`);
});

In the above code, we set up an Express server and created a POST API endpoint for the /post route. Inside the endpoint function, we destructured the request body to get the token data that will be sent from the client side.

Then we created an axios.post request to Google’s API with our SECRET_KEY passed in as an environment variable, as well as the token from the client side.

To set up an environment variable in Node.js, cd back to the react-node-app folder and run the following command:

npm install dotenv --save

After installation, create a .env file within the react-node-app folder, open the file, then add your site’s secret key.

Beneath the axios.post request is an if statement that checks the status of the response returned by the API and sends it to the client side.

Ok, let’s move on. Navigate back to the react-node-app folder, open the package.json file, and replace the script command with the following:

…
"scripts": {
  "start": "node server/index.js"
},
…

The above code will let us start our server using the npm start command when we run it in the terminal.

Save the project. Then, go to your terminal, open a new terminal tab, cd into the server folder, and start the server by running npm start.

Checking the user’s score

Next, we’ll send an axios.post request from the client side (React app) to our server, with the generated token as the data.

To do this, navigate back to your React app and paste the following code inside the handleSubmit function we created earlier:

 const handleSubmit = async (e) =>{
        e.preventDefault();

        const token = captchaRef.current.getValue();
        captchaRef.current.reset();

        await axios.post(process.env.REACT_APP_API_URL, {token})
        .then(res =>  console.log(res))
        .catch((error) => {
        console.log(error);
        })
    }

This code is an axios.post request that sends the generated token from reCAPTCHA to the Node.js backend.

If you save your code and run the app, you should see a reCAPTCHA form similar to this:

Captcha Form Console

Using the reaptcha wrapper

react.captcha (Reaptcha) is an alternative solution for implementing reCAPTCHA in React. The library shares similar features with react-google-recaptcha, but unlike the former, Reaptcha handles reCAPTCHA’s callbacks inside React components and automatically injects the reCAPTCHA script into the head DOM element.

This way, your applications would not have to depend on the library and directly communicate with the reCAPTCHA API when deployed.

To install Reaptcha, run the following command within your terminal:

npm install --save reaptcha

After installation, go to the form.js file and import the Reaptcha component like so:

import Reaptcha from 'reaptcha';

The Reaptcha component provides several props that can be used to customize the rendering. Here is a list of the available props:

  • sitekey: This prop accepts the client key (site key we generated in the previous sections)
  • theme: an optional prop for changing the widget’s appearance (light or dark)
  • onLoad: an optional callback function that gets called when the Google reCAPTCHA script has been loaded
  • onVerify: an optional callback function that gets called when a user completes the captcha
  • onExpire: an optional callback function that gets called when the challenge is expired and has to be redone
  • explicit: an optional prop that allows the widget to be rendered explicitly, i.e., invisible
  • size: an optional prop that allows you to change the size of the widget to either of these: compact, normal, invisible
  • ref: prop used for accessing the component’s instance methods

Although most of these props look similar to the ones exposed by the react-google-recaptcha’s component, not all of them work as you’d expect. The ref prop for one doesn’t have a method like getValue() for getting the response token. Instead, it uses a getResponse() instance method that returns the token with a promise.

Therefore, adding the component to the form component and retrieving the response token will be as follows:

const [captchaToken, setCaptchaToken] = useState(null);
const captchaRef = useRef(null);

const verify = () =>{
        captchaRef.current.getResponse().then(res => {
            setCaptchaToken(res)
        })

    }

return(
        <form onSubmit={handleSubmit} >
            <Reaptcha 
       sitekey={process.env.REACT_APP_SITE_KEY}
       ref={captchaRef}
       onVerify={verify} 
      >
        </form>
    )
}

Here, we created a verify function. Inside it, we’re fetching the response token from the ref variable using the getResponse() instance method. Since the method returns a promise, we chained a then method to it and pass the response to the captchaToken state variable.

We also pass the verify function to the onVerify prop on the component so that the function will only attempt to fetch the responses token when a user completes the captcha.

The component’s instance methods are utility functions that can be called to perform certain actions. Just as we used the getResponse method to grab the response token earlier, we can use other methods to perform different actions, like resetting the widget after every form submission. Here is a list of available instance methods:

  • reset
  • renderExplicitly
  • execute
  • getResponse

Visit the documentation to learn more about these methods and the Reapatcha library.

That’s it! You’ve successfully implemented a working Google reCAPTCHA and a backend server that verifies users’ responses in React.

Conclusion

In this article, we examined what reCAPTCHA is and how it works. We also walked through a tutorial to demonstrate how to implement reCAPTCHA in a React application and how to verify a user’s response token with a Node.js backend server.

I hope this article will help you build secure and bot-free React applications.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

David Omotayo Frontend developer and indie game enthusiast.

4 Replies to “How to implement reCAPTCHA in a React application”

  1. Great post. I ran into some trouble after naming my component in lower case and React wasnt reconizing it as a component until i changed it lo upper case.

  2. Thank you, Mark. React components always start with uppercase letters. The library treats any component with lowercase initials as HTML elements.

    1. Hi Rasam, you have to perform a conditional check based on the response you get from the server. If it’s positive, submit the form. If not, do otherwise. I hope this helps.

Leave a Reply