Integrating Google reCAPTCHA with a Next.js Form
In this blog, we will learn how to integrate Google reCAPTCHA with a Next.js contact form to prevent spam submissions and enhance the security of the form.
Google reCAPTCHA is a free service provided by Google that helps protect websites from abusive activities by bots. By adding reCAPTCHA to our contact form, we can ensure that only human users can submit the form while reducing the chances of receiving spam.
Please refer to my previous blog on building a Contact Us form in Sitecore using Nextjs and Nodemailer.
Prerequisites
Before proceeding, ensure that you have the following set up:
- A working Next.js project with a contact form and corresponding json rendering in sitecore implemented.
- A Google reCAPTCHA API key. If you don't have one, you can get it by registering your website with the Google reCAPTCHA service.
Create a Google reCAPTCHA Account
- Go to the Google reCAPTCHA website (https://www.google.com/recaptcha) and log in with your Google account.
- Click on the "Admin Console" button to create a new reCAPTCHA project.
- Fill in the required information, such as the label (name) of your project and the domains where the reCAPTCHA will be used.
- Choose the reCAPTCHA type. For this tutorial, we'll use "reCAPTCHA v2" with the "Checkbox" option.
- Add the domain(s) where you'll implement the reCAPTCHA and accept the terms of service.
- After successfully registering your site, you'll receive the Site Key and Secret Key. Keep these keys secure, as the Secret Key should never be exposed on the client-side.
Install react-google-recaptcha Package
To use the ReCAPTCHA component, we need to install the react-google-recaptcha package. Run the following command in your project directory:
npm install react-google-recaptcha
Adding reCAPTCHA to the Contact Form
In the component where you have implemented the contact form, add the reCAPTCHA widget to the form. Update your ContactUsForm.tsx component as follows:
//...(Existing imports)
import ReCAPTCHA from 'react-google-recaptcha';
//...(Sitecore fields)
const FORM_DEFAULT: {
[key: string]: string;
} = {
firstName: '',
lastName: '',
message: '',
captchaToken: '',
};
const ContactUsForm = ({ fields }: ContactUsFormProps): JSX.Element => {
const [formData, setFormData] = useState(FORM_DEFAULT);
const [successMsgCss, setSuccesssMsg] = useState(false);
// Create a ref for the reCAPTCHA widget
const recaptcha: RefObject<ReCAPTCHA> = useRef(null);
// ... (Existing functions)
const formSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
formData.recipient = fields.emailRecipient.value;
formData.emailSubject = fields.emailSubject.value;
fetch('/api/contact', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, /',
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
.then((response) => {
console.log('response recieved');
if (response.status === 200) {
console.log('response succeeded');
setSuccesssMsg(true);
setFormData(FORM_DEFAULT);
recaptcha?.current?.reset();// reset recaptcha after submission
}
})
.catch((error) => {
console.error(error);
});
}
};
const onCaptchaChange = (token: string | null) => {
// Set the captcha token when the user completes the reCAPTCHA
if (token) {
formData.captchaToken = token;
}
};
return (
{/* ... (existing TSX markup) /}
<div className="pr-15px pl-25px pt-50px pb-25px mx-auto max-w-1200px w-full">
<div>
{/ ... (existing form fields) /}
{/ Add the reCAPTCHA widget /}
<div className="pb-20px">
<ReCAPTCHA
size="normal"
sitekey="YOUR_RECAPTCHA_SITE_KEY"
onChange={onCaptchaChange}
ref={recaptcha}
/>
</div>
{/ ... (existing submit button) */}
</form>
</div>
Server-Side Verification
Update your API route (/pages/api/contact.ts) to validate the reCAPTCHA token received from the frontend:
//...existing imports
import axios from 'axios';
export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise<void> {
// ... (existing transporter setup and mailData)
// Validate the reCAPTCHA token on the server-side
try {
const response = await axios.post(
https://www.google.com/recaptcha/api/siteverify?secret=<span class="hljs-subst">${process.env.RECAPTCHA_SECRET_KEY}</span>&response=<span class="hljs-subst">${req.body.captchaToken}</span>
);
if (response.data.success) {
//reCaptcha verification successfull
transporter.sendMail(mailData, function (err, info) {
if (err) {
console.log(err);
res.status(500).send('Internal Server Error');
} else {
console.log('successful');
console.log(info);
res.status(200).end();
}
});
} else {
// reCAPTCHA verification failed
res.status(400).send('reCAPTCHA verification failed.');
}
} catch (error) {
console.error(error);
res.status(500).send('Internal server error');
}
}
In this above code, we use axios.post to send a POST request to the Google reCAPTCHA API endpoint (https://www.google.com/recaptcha/api/siteverify). We pass the reCAPTCHA token and the reCAPTCHA secret key in the request body. The response contains the verification result, which we check to ensure the reCAPTCHA was successful. If the reCAPTCHA verification succeeds, we proceed with sending the email; otherwise, we return an error response.
Conclusion
In this blog post, we learned how to add Google reCAPTCHA to your existing Next.js contact form. By integrating reCAPTCHA, you can enhance the security of your form and prevent automated spam submissions. Implementing reCAPTCHA is a straightforward process and provides an added layer of protection for your website's forms.