Google Invisible reCAPTCHA with React and Node JS
Website security is the process of protecting websites and online services against different security threats that exploit vulnerabilities in an application and making sure it is safe for visitors. Without proper attention to website security, there are chances of below mentioned exploitations on the website,
- data breach
- taking the website offline,
- script injections, and
- forgery etc.
The impacts of a hacked website can include financial loss, brand reputation issues, and poor search engine rankings.
A bot — short for “robot” and also called an internet bot can also be used for hacking your websites, apis or any other supporting systems for the website.
One of the methods to avoid these security issues is to use Google reCAPTCHA
The motivation behind using reCAPTCHA internally is…
Intrusion of external sources were detected on one of the apis which provided the details for a particular scenario. The response data of the api were crawled by the hackers/bots. These crawling of data were happening on regular intervals, as these were exposed at our client. This was a challenging part for us to secure an open api.
The above graph shows the brief information on crawling of data which were high at regular intervals of time. This continued for several days in similar manner, several actions such as creating random keys and passing down to the backend were taken in order to avoid the crawling of data, however the issue still pertained.
The reason is that, any logic/implementations done on the client side can be easily found and authentications on browser can be hacked by anyone.
How Google reCAPTCHA helped resolving the issue?
reCAPTCHA uses an advanced risk analysis engine and adaptive challenges to keep malicious software from engaging in abusive activities on your website. Meanwhile, legitimate users will be able to login, make purchases, view pages, or create accounts and fake users will be blocked.
Following are some of the use cases.
- Data scraping
- False posts
- Account takeovers
- Junk injection on form submission
- Fraudulent transactions
So how does reCAPTCHA work?
reCAPTCHA is a CAPTCHA system that enables web hosts to distinguish between human and automated access to websites.
reCAPTCHA uses an advanced risk analysis engine and adaptive challenges to keep malicious software from engaging in abusive activities on your website. Meanwhile, legitimate users will be able to login, make purchases, view pages, or create accounts and fake users will be blocked.
reCAPTCHA has been at the forefront of bot mitigation for over a decade and actively protects data for our network of five million sites.
The reCAPTCHA can be added not just on the client side in react, but also on the server side.
The way it works is,
On the client side, you get access to the reCAPTCHA token.
You send this token to the backend.
Google verifies the token and gives us the response JSON object in the below format, which lets us know whether it is a success or not, basically specifying whether it is a bot or human.
{
"success": true|false,
"challenge_ts": timestamp
"hostname": string,
"error-codes": [...]
}
Google’s response can be used to decide whether we should allow the user to access information/data or not.
reCAPTCHA setup
The first thing which needs to be done when dealing with the reCAPTCHA is to register a new site in the Admin Console,
- providing necessary label,
- reCAPTCHA type,
- domains and
- owners.
There are two versions of reCAPTCHA,
- reCAPTCHA v3
- reCAPTCHA v2
One may think that going for v3 is a better option because it is one version more advanced than v2, but they both do different things.
reCAPTCHA v3 gives a score between 0 and 1, basically how likely it is a human or not. With v3, Google is improving the experience even more, with the API returning a score between 0.0 and 1.0 that ranks “how suspicious an interaction is.” It is intended for power users, site owners that want more data about their traffic, and for use cases in which it is not appropriate to show a challenge to the user. It clearly improves the experience for human users by eliminating the need to disrupt their browsing with reCaptcha challenges. It scores traffic with its Adaptive Risk Analysis Engine instead of forcing human users to perform interactive challenges.
reCAPTCHA v2 pops up a challenge image asking users to click specified images like bicycle, boats, hydrants etc. With reCaptcha v2, the only required action is to verify whether the user correctly solved the challenge or not. reCAPTCHA v2 with invisible reCAPTCHA badge does not require the user to click on a checkbox, instead it is invoked directly when the user clicks on an existing button on your site or can be invoked via a JavaScript API call.
The integration requires a JavaScript callback when reCAPTCHA verification is complete. By default only the most suspicious traffic will be prompted to solve a captcha.
reCAPTCHA v2 with checkbox requires the user to click a checkbox indicating the user is not a robot. This will either pass the user immediately (with No CAPTCHA) or challenge them to validate whether or not they are human. It is the simplest option to integrate with and only requires two lines of HTML to render the checkbox.
At redBus, we started with the implementation using reCAPTCHA v2 which resulted in popping of challenge images every time anyone landed on that particular page. Whether or not you get the full challenge will depend on how confident Google is that you really are a human. Hence sometimes there used to be challenge images coming up more times than expected.
Therefore, we opted to go with the reCAPTCHA v3 implementation which doesn't involve any user interactions.
Hence you need to choose which one works better for your application!
Upon agreeing terms and conditions, a new site will be created with a specific site key (which will be public and used on client side) and a secret key (private and used on the backend). These keys can be added on environment variables, configs etc in the codebase.
reCaptcha Implementation Details
Tech Stack: React + Typescript
Package used: react-google-recaptcha ( npm i react-google-recaptcha)
Client Side Integration
In react code, we start with importing reCAPTCHA from react-google-recaptcha package.
import ReCAPTCHA from ‘react-google-recaptcha’;
In the required component, we can add the reCAPTCHA just as any other tag with few props that are required to work properly such as the sitekey
.
<ReCAPTCHA
className={recaptchaClass}
sitekey={RECAPTCHA_SITEKEY}
size="invisible"
ref={reCaptchaRef}
/>
Here, the “size” specifies that we need to use invisible one vs click a checkbox one. In our case, we didn’t wanted to interrupt user to select images to verify. Hence we chose size=”invisible”
.
When dealing with the invisible one, we need to sort of programmatically tell it to execute. In order to do that, we will need access to ref (reCaptchaRef
). This ref can be implemented in different ways for stateful and stateless components, let me focus on stateless approach here,
const reCaptchaRef<ReCAPTCHA> = useRef();
We use this ref
just prior to posting data to the server. To do this, we need to get access to the token that reCAPTCHA gives us.
const token = await reCaptchaRef.current.executeAsync();
With the token in hand, which is, of type ‘string’, we can pass this token up to the server. We can also check this token by logging it on the console. If everything is working fine on the client side, then we should be able to see protected by logo showing on the screen.
It’s required to reset the reCAPTCHA so that it is ready for subsequent checks again and the way to do that is,
reCaptchaRef.current.reset();
So by calling reset, it allows you to re-execute the recaptcha check subsequent times.
And THAT’S ALL …~!! The client side aspect couldn't be any simpler and straight forward, right!??
Let’s hop on to the server-side implementations.
Server Side Integration
To validate the data that was received from the client, we need to define a function that basically takes this data (token), sends it off to Google and Google responses back whether it was a success or not. Here, the secret key is required in order to send data to Google.
async ValidateHuman(token: string){
return new Promise(function(resolve, reject){
const secretKey = config.RECAPTCHA_SECRET_KEY;
const response =
fetch(`https://www.google.com/recaptcha/api/siteverify?
secret=${secretKey}&response=${token}`,
{
method: 'POST'
});
const data = await response.json();
}
}
What they mean by this is that, it’s a sort of human check response that was done on the client, that results in the token.
We call the above function just before the api and in general case it would be before the activity which needs a check. For example, tasks such as form submissions and validations.
In case of a successful response, we proceed with the next task otherwise we throw an error.
Conclusion:
reCAPTCHA can be very helpful in distinguishing between human and bots, providing enhanced security over the api hackings, data crawling and any suspicious activities thus protecting your website from fraud and abuse.
The following graph shows a gradual reduction in api data crawling post the implementation of reCAPTCHA on redBus site.
The version of reCAPTCHA to be used, depends on what kind of implementation is required on the website.
If there is a need for any user interaction or to get thorough confirmation that it’s human, then it’s good to go with v2. This works best for the client side implementations.
reCAPTCHA v3 will never interrupt your users, so you can run it whenever you like without affecting conversion. This works best in case of api calls and data related security.
Additional Resources: