Tutorials

Implementing Google reCAPTCHA V3

September 17th, 2024 | By Jay Raj | 10 min read

In one of our previous tutorials we already covered how to integrate Google reCaptcha v2 into our Next.js application. In this tutorial, you'll learn how to integrate Google reCaptcha v3 into your Next.js application. Unlike the reCaptcha v2 where the user is prompted with a check box or a challenge for the user when suspicious, reCaptcha v3 returns a score based on which we can take appropriate action for the user flow.


Let's get started by registering our website for a reCaptcha v3 to get the site key and secret.


Registering Site for reCaptcha v3


Navigate to the Google reCaptcha admin console and register your website.


Register the site by clicking submit and don't forget the site key and secret. Up next, let's create our Next.js application where we'll be integrating the Google reCaptcha v3.


Creating Next.js Application


You'll need Node.js 18.17 or later installed in your system to create a Next.js application. For creating the project run:

npx create-next-app@latest


The above command will prompt you to enter a couple of details, please enter the details as shown:

√ What is your project named? ... recaptcha-v3
√ Would you like to use TypeScript? ... Yes
√ Would you like to use ESLint? ... No
√ Would you like to use Tailwind CSS? ... No
√ Would you like to use `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... No
√ Would you like to customize the default import alias (@/*)? ... No


Navigate to the project directory and start the Next.js web app.

cd recaptcha-v3
npm run dev


Navigate to http://localhost:3000/ and you can view the default boilerplate view. Now let's integrate reCaptcha v3 into our application.


Adding Google reCaptcha v3 

For integrating Google reCaptcha v3 into our Next.js application we'll be using the `react-google-recaptcha-v3` module.


Install `react-google-recaptcha-v3` from your project console.


npm install react-google-recaptcha-v3 --save

Once the package is installed, import `GoogleReCaptchaProvider` from `react-google-recaptcha-v3` inside the `src/_app.tsx` file.


import { GoogleReCaptchaProvider } from  'react-google-recaptcha-v3';

Include `GoogleReCaptchaProvider` inside the `App` component in `_app.tsx`.


<GoogleReCaptchaProvider reCaptchaKey="xxxxxx">
   <Component {...pageProps} />
</GoogleReCaptchaProvider>


Replace the `reCaptchaKey` in the above code with the site key you have from registering the app in Google reCaptcha admin.


Save the above changes and reload the application page. You will be able to see the reCaptcha logo on the lower right side of the web page. If you are able to see the logo it means Google reCaptcha has been loaded successfully on your website.


Next, let's create a component with a simple form. When the form is submitted we'll check for captcha verification.


Creating Simple Form Component

Inside the `src` folder create another folder called `components`. Inside `components` create a component `registration/registration.tsx`. Here is how it looks:

 

const Registration = () => {
    return (
        <>
            <form onSubmit={handleReCaptchaVerify}>
                <input type="text" />
                <button>
                    Submit
                </button>
            </form>
            
        </>
    )
}

export default Registration;

Next import `useGoogleReCaptcha` from `react-google-recaptcha-v3`. 


We'll be using `useGoogleReCaptcha` to execute reCaptcha. Start by importing `executeRecaptcha` from `useGoogleReCaptcha`.


const { executeRecaptcha } =  useGoogleReCaptcha();


Now we'll use the `executeRecaptcha` method to generate the reCaptcha token. The method `executeRecaptcha` takes as input an action name which we'll mention as `signup`. Here is how the complete `registration.tsx` file looks:


import { useCallback } from 'react';
import {
    useGoogleReCaptcha
  } from 'react-google-recaptcha-v3';

const Registration = () => {

    const { executeRecaptcha } = useGoogleReCaptcha();

    const handleReCaptchaVerify = useCallback(async ($event: any) => {
        $event.preventDefault();

        if (!executeRecaptcha) {
        console.log('executeRecaptcha not yet available');
        return;
        }

        const token = await executeRecaptcha('signup');
        console.log('token is ', token);
    }, [executeRecaptcha]);

    return (
        <>
            <form onSubmit={handleReCaptchaVerify}>
                <input type="text" />
                <button>
                    Submit
                </button>
            </form>
            
        </>
    )
}

export default Registration;


Include the `Registration` component in the `index.tsx` file.

<Registration>
</Registration>


Save the changes and reload the web application. Click the button on the page and check the browser console. You'll find the reCaptcha token being generated.


Up next, we'll be required to verify this generated token using the `secret` at the back end once the form is submitted.  For the sake of this tutorial, we'll create an API endpoint and verify the token using the `secret`.


Verifying reCaptcha Token


Inside the `src/pages/api` create a file called `verifyToken.ts`. This is the API endpoint that we'll be using to verify the reCaptcha token. 


From inside the API, we'll send a POST request to https://www.google.com/recaptcha/api/siteverify to verify the generated token. Let's start by parsing the token from the request query inside the API.


import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
  success: boolean,
  score:  number
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  try{
    const secret = 'xxxxxxxxxx';
    const {token} = req.query; 
    
  } catch(error:any){
    console.log('Error is ', error);
    res.status(500).json({ success: false }) 
  }
}

Once you have the token, as discussed you need to send the token to Google API to verify.


const fetchQuery = await fetch(`https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${token}`,{
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
})

After parsing the API response we'll return whether the token is valid or not using `success` and the token score using `score` key in the response object.


Here is how the entire `verifyToken.ts` file looks:

import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
  success: boolean,
  score: number
}

export default async function handler(
  req: NextApiRequest
  res: NextApiResponse<Data>
) {
  try{
    const secret = 'xxxxxxxxxxxxx';
    const {token} = req.query; 
    const query = await fetch(`https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${token}`,{
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
    })
    const apiResponse = await query.json();
    res.status(200).json({ success: apiResponse?.success, score : apiResponse?.score }) 
  } catch(error:any){
    console.log('Error is ', error);
    res.status(500).json({ success: false, score: -1 }) 
  }
}

Now open the `registration.tsx` file and inside the `handleReCaptchaVerify` method once the token is generated, make an API call to `/api/verifyToken` to verify the generated token.


if (token) {
     const query:any = await fetch(`/api/verifyToken?token=${token}`)
     const {success} = await query.json();
     if(success){
        alert('Token verified');
     } else {
        alert('Token verification failed');
     }
 } else {
     alert('Error getting token');
 }


Here is how the modified `registration.tsx` file looks:


import { useCallback } from 'react';
import {
    useGoogleReCaptcha
  } from 'react-google-recaptcha-v3';

const Registration = () => {

    const { executeRecaptcha } = useGoogleReCaptcha();

    const handleReCaptchaVerify = useCallback(async ($event: any) => {
        $event.preventDefault();

        if (!executeRecaptcha) {
        console.log('executeRecaptcha not yet available');
        return;
        }

        const token = await executeRecaptcha('signup');
        console.log('token is ', token);

        if (token) {
            const query:any = await fetch(`/api/verifyToken?token=${token}`)
            const {success, score} = await query.json();
            if(success){
              alert('Token verified ' + score);
            } else {
              alert('Token verification failed ' + score);
            }
        } else {
            alert('Error getting token');
        }
    }, [executeRecaptcha]);

    return (
        <>
            <form onSubmit={handleReCaptchaVerify}>
                <input type="text" />
                <button>
                    Submit
                </button>
            </form>
        </>
    )
}

export default Registration;


Now if you save the above changes, reload the app, and click on the button, you'll be able to see the token verification status along with the score. From the official docs, "1.0 is very likely a good interaction, and 0.0 is very likely a bot".


Wrapping it Up

In this tutorial, you learned how to register and integrate Google reCaptcha v3 into your Next.js application. Captcha is a very useful tool that keeps spam and bots away from your web application to a large extent.


Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Tutorials

Implementing Google reCAPTCHA V2 for Next js Application

reCAPTCHA is a service that helps in identifying humans from bots. In this tutorial, you'll learn how to implement Google reCAPTCHA v2 into your Next.js application.

March 5, 2024 | By Jay Raj | 11 min read

Tutorials Web Development

Building API Using Next.js

In this development tutorial, we'll explore how to build APIs using Next.js 14. The newer version of Next.js provides the platform to create APIs using the App router.

July 30, 2024 | By Jay Raj | 10 min read

Section Divider