CAPTCHA stands for Completely Automated Public Turing Test to tell Computers and Humans apart. It is a type of security measure which protects your application against bots and helps you detect abusive traffic. Google reCaptcha v3 is a service provided by google which uses risk analysis techniques to detect and block spam traffic without user interaction. Let’s us see how to implement it in React and Go.
How it works
The google reCaptcha v3 service gives two keys- a site key and a secret key for validation. The site key is used for token generation in the client side and secret key is used for validation in server side. The token generated using site key is sent to the server for verification. Generally, it is sent during any form submission along with the form values. In the server, the the request is verified using the endpoint:
https://www.google.com/recaptcha/api/siteverify
The secret key stored in server and the token received from client are sent in the body of this request as x-www-form-urlencoded values. It returns an error if the keys or token does not match. In case of successful request, it returns a score between 0.0 and 1.0 where 1.0 indicates a human and 0.0 indicates a bot. The threshold value to block or allow the traffic is set according to the needs of our application. More on this later in the article.
Service Setup
- Go to https://www.google.com/recaptcha/admin/create and register your application.
- Enter your app name in label.
- Select reCaptcha type as Score based (v3).
- Enter your domain name in which your app will be hosted. For local testing, add localhost in it.
- Once you finish, you’ll get the site key and secret key. Copy them both as we will use them later.
Code Setup
- Install react-google-recaptcha-v3 package:
npm i react-google-recaptcha-v3
- Get reCaptcha token and send it to the server:
import React, { useState } from "react";
import { GoogleReCaptchaProvider, useGoogleReCaptcha } from "react-google-recaptcha-v3";
const RECAPTCHA_SITE_KEY = "your-site-key"; // Replace with your actual site key
const MyForm = () => {
const { executeRecaptcha } = useGoogleReCaptcha();
const [formData, setFormData] = useState({});
const handleSubmit = async (e) => {
e.preventDefault();
if (!executeRecaptcha) {
console.log("reCAPTCHA not loaded yet");
return;
}
// Execute reCAPTCHA to get the token
const recaptchaToken = await executeRecaptcha("submit");
// Send form data + token to backend
const response = await fetch("http://localhost:8080/api/verify-recaptcha", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...formData, recaptchaToken }),
});
const data = await response.json();
if (data.success) {
alert("Form submitted successfully!");
} else {
alert("reCAPTCHA verification failed. Please try again.");
}
};
return (
// your form
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
};
// Wrap your app with GoogleReCaptchaProvider
const App = () => (
<GoogleReCaptchaProvider reCaptchaKey={RECAPTCHA_SITE_KEY}>
<MyForm />
</GoogleReCaptchaProvider>
);
export default App;
- Verify the token and process the form submission:
type RecaptchaResponse struct {
Success bool `json:"success"`
Score float64 `json:"score"`
}
func VerifyRecaptchaToken(token string) error {
var recaptchaResponse RecaptchaResponse
secretKey := os.Getenv("RECAPTCHA_SECRET_TOKEN")
resp, err := http.PostForm("https://www.google.com/recaptcha/api/siteverify",
url.Values{
"secret": {secretKey},
"response": {token},
})
if err != nil {
return err
}
defer resp.Body.Close()
if err := json.NewDecoder(resp.Body).Decode(&recaptchaResponse); err != nil {
return err
}
thresholdNumber := constant.DEFAULT_RECAPTCHA_THRESHOLD
// verification failed or score less than set threshold
if !recaptchaResponse.Success || recaptchaResponse.Score <= thresholdNumber {
return errors.New("verification failed")
}
// process the form submission
return nil
}
Score and Threshold
As we know now, the reCaptcha verification API returns a score. The request is blocked or allowed based on that score and the set threshold. The threshold value is set according to the application. Generally a value of 0.5 as threshold is widely used. It means score less than 0.5 will be marked as a bot and anything greater than that is allowed.
If the user on the application has logged in, the chances of bot requests become less. In these cases we can set the threshold around ~0.5. If the application has an open form, without authentication, increasing the threshold should be considered — preferably somewhere around ~0.7 as the chances of bot requests are higher.
The behaviour of the requests with low scores can also be configured. Some common methods of dealing with such requests are OTP/email verification, reCaptcha v2(challenge), manual reviews or blocking them straight away.
Conclusion
I hope you enjoyed the article, any suggestions/improvements are welcome.
Reach out to me at sakshamnegi.dev@gmail.com for any questions, feedback, or collaboration opportunities.
Top comments (0)