Using reCAPTCHA v3 with Next.js 14

Using useFormState and useActionState

Next.js documentation currently encourages the use of useFormState and useActionState to submit form data to your server actions.

I will show you how I got Google’s reCaptcha v3 working with useFormStat…


This content originally appeared on DEV Community and was authored by Zach Koch

Using useFormState and useActionState

Next.js documentation currently encourages the use of useFormState and useActionState to submit form data to your server actions.

I will show you how I got Google's reCaptcha v3 working with useFormState. This may also apply to useActionState, but I have not tested it.

Setting up reCAPTCHA

Go to the reCAPTCHA v3 admin console and create a new site if you don't have one yet

Your configuration should have

  • A label for your project
  • Score Based (v3) selected
  • localhost and your site url both added as domains

reCAPTCHA config

After submitting the next page will let you copy the keys that you will need to add to your project in the next section

reCAPTCHA keys

Setting up environment variables

In your project create a file called .env.local if you don't have one

In this file add your keys

.env.local

NEXT_PUBLIC_RECAPTCHA_SITE_KEY=yoursitekeygoeshere
RECAPTCHA_SECRET_KEY=yoursecretkeygoeshere

Make sure you have this file added to .gitignore

adding NEXT_PUBLIC_ to our variable allows it to be accessed in the browser

react-google-recaptcha-v3

install react-google-recaptcha-v3

npm i -S react-google-recaptcha-v3

This package comes with GoogleReCaptchaProvider, a component that runs the reCaptcha script that detects bots and provides the result to any child components.

The documentation states that it should places as high as possible in the tree, but I found that I would get errors if it was outside the bounds of a client component.

In my case I wrapped it in the same file as my form component

Contact.tsx

'use client';
import {
    GoogleReCaptchaProvider, useGoogleReCaptcha
} from 'react-google-recaptcha-v3';

export default function Contact() {
    return (
        <GoogleReCaptchaProvider
            reCaptchaKey={
                process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY ?? ''
            }>
            <ContactForm />
        </GoogleReCaptchaProvider>
    )
}

function ContactForm() {
    // my form component
}

Integrate with useFormState

Normally we would set up useFormState by providing it with a server action that handles our form data.

In this case we want to add the reCAPTCHA data just before submitting to the server.

To do this we will

  • make a function with that accepts prevState and formData
  • get our captcha response from the reCAPTCHA script using executeRecaptcha
  • attach the captcha response to our form as a form field
  • send it off to our server action

Contact.tsx just inside your form component

const initialState: MessageState = { message: null, errors: {}};
const [state, formAction] = useFormState(addRecaptcha, initialState);
const { executeRecaptcha } = useGoogleReCaptcha();

async function addRecaptcha(prevState: MessageState, formData: FormData) {
    let gRecaptchaToken = ''
    if (executeRecaptcha) {
        gRecaptchaToken = await executeRecaptcha('contactMessage');
    }
    formData.set('captcha', gRecaptchaToken);

    return createMessage(prevState, formData)
}

The form action will go at the top of your form

Contact.tsx

<form action={formAction}>
  // your form
</form>

When you submit, the token that is created by the captcha provider will be sent to your server action as just another field

Validating captcha data

In your server action you will recieve your captcha token as part of your form data.

You can send the token to Google to verify

If the verification fails you can treat it the same way you would treat validation for any failed field in your form.

Contact.tsx

async function validateCaptcha(captchaToken: string) {
    const secretKey = process.env.RECAPTCHA_SECRET_KEY;
    const captchaResponse = await fetch(
        `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captchaToken}`, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    });
    const res = await captchaResponse.json();
    return res.score;
}

const score = await validateCaptcha(formData.get('captcha') ?? '')

Hopefully that is enough to help you integrate captcha. I'll update this for useActionState in the future. I am currently using this on my own site. Let me know in the comments if you spot any issues or if anything is unclear.


This content originally appeared on DEV Community and was authored by Zach Koch


Print Share Comment Cite Upload Translate Updates
APA

Zach Koch | Sciencx (2024-09-04T20:45:35+00:00) Using reCAPTCHA v3 with Next.js 14. Retrieved from https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/

MLA
" » Using reCAPTCHA v3 with Next.js 14." Zach Koch | Sciencx - Wednesday September 4, 2024, https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/
HARVARD
Zach Koch | Sciencx Wednesday September 4, 2024 » Using reCAPTCHA v3 with Next.js 14., viewed ,<https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/>
VANCOUVER
Zach Koch | Sciencx - » Using reCAPTCHA v3 with Next.js 14. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/
CHICAGO
" » Using reCAPTCHA v3 with Next.js 14." Zach Koch | Sciencx - Accessed . https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/
IEEE
" » Using reCAPTCHA v3 with Next.js 14." Zach Koch | Sciencx [Online]. Available: https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/. [Accessed: ]
rf:citation
» Using reCAPTCHA v3 with Next.js 14 | Zach Koch | Sciencx | https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.