DEV Community

Cover image for Implementing Google reCAPTCHA in a Simple React and Node.js App
Shilleh
Shilleh

Posted on

Implementing Google reCAPTCHA in a Simple React and Node.js App

In today’s digital landscape, protecting your applications from bots and spam is crucial. One effective way to add an extra layer of security to your forms is by integrating Google reCAPTCHA.

CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) is a type of challenge-response test used in computing to determine whether the user is human. It helps prevent automated software from performing actions that can degrade the quality of service.

reCAPTCHA is a more advanced form of CAPTCHA developed by Google, which not only protects websites from spam and abuse but also helps digitize text, annotate images, and build machine learning datasets. It often involves identifying objects in images or simply checking a box that says “I’m not a robot.”

A robot or automated script could, in theory, attempt to click a CAPTCHA checkbox, but modern CAPTCHA systems like reCAPTCHA use various techniques to distinguish human behavior from automated scripts. These techniques include:

Behavior Analysis: reCAPTCHA analyzes user behavior, such as mouse movements, keystrokes, and the time taken to complete tasks, to determine if the user is human.
Challenges: If the behavior analysis is inconclusive, reCAPTCHA may present additional challenges, such as identifying objects in images or solving puzzles, which are designed to be difficult for bots.
Machine Learning: reCAPTCHA uses machine learning algorithms to continually improve its ability to differentiate between humans and bots based on data collected from users.
These methods make it challenging for automated scripts to successfully bypass CAPTCHA systems.

This blog post will walk you through the process of implementing Google reCAPTCHA in a simple React and Node.js application. We’ll cover both the frontend and backend, ensuring that reCAPTCHA verification is seamlessly integrated into your login process.

Link to GH Project:

https://github.com/shillehbean/youtube-p2/tree/main/reCAPTCHA-react

— — -

Before we delve into the topic, we invite you to support our ongoing efforts and explore our various platforms dedicated to enhancing your IoT projects:

  • Subscribe to our YouTube Channel: Stay updated with our latest tutorials and project insights by subscribing to our channel at YouTube — Shilleh.
  • Support Us: Your support is invaluable. Consider buying me a coffee at Buy Me A Coffee to help us continue creating quality content.
  • Hire Expert IoT Services: For personalized assistance with your IoT projects, hire me on UpWork.

ShillehTek Website (Exclusive Discounts):

https://shillehtek.com/collections/all

ShillehTekAmazon Store:

ShillehTek Amazon Store — US

ShillehTek Amazon Store — Canada

ShillehTek Amazon Store — Japan

*Step 1: Set Up Your React and Node.js Environment
*

First, ensure you have Node.js and npm installed on your machine. If not, download and install them from https://nodejs.org/en.

Step 2: Create a New React App

Create a new React application using Create React App:

npx create-react-app recaptcha-demo
cd recaptcha-demo
Enter fullscreen mode Exit fullscreen mode

*Step 3: Install Necessary Packages
*

We’ll use react-google-recaptcha for integrating reCAPTCHA into our React app:

Installing ajv manually with npm install --save-dev ajv@^7 resolves a missing module error by ensuring the correct version is available for your project dependencies.

npm install --save-dev ajv@^7
npm install react-google-recaptcha axios react-toastify
Enter fullscreen mode Exit fullscreen mode

Step 4: Create Your Node.js Backend

Set up your Node.js backend by creating a new directory and initializing a new Node.js project:

cd ..
mkdir backend
cd backend
npm init -y
npm install express axios dotenv cors jsonwebtoken express-async-handler
npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Image description

Your directory structure should look like this.

*Step 5: Set Up Google reCAPTCHA
*

Go to the Google reCAPTCHA Admin Console at https://www.google.com/recaptcha/admin/create to register your site. You will receive a Site Key and a Secret Key. Save these keys for use in your application.

*Step 6: Set Up Your Environment Variables
*

Create a .env file in your backend directory and add your Google reCAPTCHA keys:

CAPTCHA_SECRET_KEY=your-secret-key
JWT_SECRET=anything
Enter fullscreen mode Exit fullscreen mode

Create a .env file in your React project directory and add your Google reCAPTCHA site key:

REACT_APP_CAPTCHA_SITE_KEY=your-site-key
Enter fullscreen mode Exit fullscreen mode

*Step 7: Create Backend Middleware for reCAPTCHA Verification
*

Create a middleware directory and add recaptchaMiddleware.js for handling reCAPTCHA verification:

// backend/middleware/recaptchaMiddleware.js
const axios = require('axios');
const asyncHandler = require('express-async-handler');
const verifyCaptcha = asyncHandler(async (req, res, next) => {
  const { captcha } = req.body;
  if (!captcha) {
    return res.status(400).json({ message: 'Please complete the CAPTCHA' });
  }
  const secretKey = process.env.CAPTCHA_SECRET_KEY;
  try {
    const response = await axios.post(
      `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captcha}`
    );
    if (response.data.success) {
      next();
    } else {
      return res.status(400).json({ message: 'CAPTCHA verification failed' });
    }
  } catch (error) {
    return res.status(500).json({ message: 'CAPTCHA verification error' });
  }
});
module.exports = { verifyCaptcha };
Enter fullscreen mode Exit fullscreen mode

Step 8: Create Your Express Server

Set up an Express server and use the middleware for reCAPTCHA verification:

// backend/server.js
const express = require('express');
const dotenv = require('dotenv');
const cors = require('cors');
const { verifyCaptcha } = require('./middleware/recaptchaMiddleware');
const jwt = require('jsonwebtoken');

dotenv.config();
const app = express();
app.use(cors());
app.use(express.json());
app.post('/api/login', verifyCaptcha, (req, res) => {
  const { email, password } = req.body;
  if (email === 'test@example.com' && password === 'password') {
    const token = jwt.sign({ id: 1, email }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).json({ message: 'Invalid credentials' });
  }
});
const PORT = process.env.PORT || 5002;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

*Step 9: Integrate reCAPTCHA in React
*

In your React app, create a login form that includes the reCAPTCHA component:

// src/Login.js
import React, { useState } from 'react';
import axios from 'axios';
import ReCAPTCHA from 'react-google-recaptcha';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import './Login.css'; // Import the CSS file

const Login = () => {
  const [formData, setFormData] = useState({ email: '', password: '', captcha: '' });
  const [isLoggedIn, setIsLoggedIn] = useState(false); // Add state for login status
  const { email, password, captcha } = formData;

  const onChange = (e) => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const onCaptchaChange = (value) => {
    setFormData({ ...formData, captcha: value });
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!captcha) {
      toast.error('Please complete the CAPTCHA');
      return;
    }
    try {
      const response = await axios.post('http://localhost:5002/api/login', { email, password, captcha });
      toast.success('Login successful');
      setIsLoggedIn(true); // Set login status to true on success
      console.log(response.data); // Handle the response
    } catch (error) {
      toast.error(error.response.data.message || 'Login failed');
    }
  };

  return (
    <div className="login-container">
      {isLoggedIn ? (
        <div className="success-message">
          <h1>Login Successful</h1>
        </div>
      ) : (
        <form className="login-form" onSubmit={onSubmit}>
          <input
            type="email"
            name="email"
            value={email}
            onChange={onChange}
            placeholder="Email"
            required
          />
          <input
            type="password"
            name="password"
            value={password}
            onChange={onChange}
            placeholder="Password"
            required
          />
          <div className="captcha-container">
            <ReCAPTCHA
              sitekey={process.env.REACT_APP_CAPTCHA_SITE_KEY}
              onChange={onCaptchaChange}
            />
          </div>
          <button type="submit">Login</button>
        </form>
      )}
      <ToastContainer position="top-right" autoClose={5000} />
    </div>
  );
};

export default Login;
Enter fullscreen mode Exit fullscreen mode
/* src/Login.css */
.login-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f5f5f5;
  }

  .login-form {
    background: #fff;
    padding: 2rem;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
    width: 300px;
  }

  .login-form input {
    margin-bottom: 1rem;
    padding: 0.75rem;
    border: 1px solid #ccc;
    border-radius: 4px;
  }

  .captcha-container {
    display: flex;
    justify-content: center;
    margin-bottom: 1rem;
  }

  .login-form button {
    padding: 0.75rem;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }

  .login-form button:hover {
    background-color: #0056b3;
  }

  .success-message {
    background: #fff;
    padding: 2rem;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    text-align: center;
  }
Enter fullscreen mode Exit fullscreen mode

*Step 10: Modify App.js file
*

import React from 'react';
import Login from './Login';
import './App.css';  // Optionally, create this file for styling

const App = () => {
  return (
    <div className="App">
      <h1>Login</h1>
      <Login />
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Run npm start in the recaptcha-demo folder

Run nodemon server.js in the backend folder

You will see the following screen.

Image description

If you login with the proper credentials and check the captcha you will see a success message

Image description

Image description

It really is that simple thanks to Google’s library implementation! Be careful of the cost as scaling over 10,000 uses per month will begin to accrue a cost in your Google Cloud account if you setup a payment method, otherwise the Captcha will fail to work if you do not have payment setup.

We went over Captcha v2 in this example but really you can use v3 and it will work similarly.

Conclusion

Implementing Google reCAPTCHA in your React and Node.js applications is a straightforward process that can significantly enhance your application’s security. By following the steps outlined in this guide, you can ensure that your forms are protected against automated abuse and spam. Remember to test your implementation thoroughly in both development and production environments to ensure it works as expected.

Top comments (0)