reCAPTCHA

Last updated

Background#

Bot attacks are rising across e-commerce platforms, leading to fraudulent transactions and significant costs. Although Centra offers post-checkout fraud prevention, early bot detection at the Checkout API level is crucial. To address this, Centra has integrated Captcha, enabling frictionless verification before checkout using tools like Google reCAPTCHA.

How does it work?#

Captcha verification consists of two parts: a script evaluated on the frontend, and a backend call to the provider, checking the result. The frontend side if often associated with a visual challenge, where you have to prove that you’re a human, but it doesn’t need to contain any direct user interaction. Google reCAPTCHA v3 does all the evaluation by itself in the background, without showing any challenge at all. Even the previous reCAPTCHA v2 has an invisible mode, with auto-evaluation based on available data points.

It’s worth noting that the list of features and behaviors, which can help discriminate between bots and real users is very big. Browser features like viewport size, installed plugins, fonts, languages, mouse movement tracking, etc. can provide enough information to confidently separate humans from bots. If there’s still not enough confidence, a challenge may be presented. This seems to be the general direction here: less user interaction traded for more data collected and processed.

These collected data points are then encoded into a string, and passed to the backend for evaluation on the side of captcha provider.

Setup#

Captcha plugin setup#

The plugin setup is very minimal, just select the captcha type and paste the secrets. To obtain them, you must first have a Google Cloud account and create a project in the admin console. Click here to learn more in Google's docs.

Recaptcha plugin config

Once it is correctly set up, a new captcha section is added to Checkout API and Shop API selection responses.

1 2 3 4 5 6 7 8 "captcha": { "pluginId": 59, "type": "reCAPTCHA_v2", "key": "[public site key]", "verifyUrl": "https://client.centra.com/api/checkout/captcha-result", "script": "<script src=\"https://www.google.com/recaptcha/api.js [...] </script>", "verified": false }

The frontend is then expected to evaluate the contents of captcha.script, which contains a callback to a new POST captcha-result endpoint. After that, the captcha.verified is true, and the script is no longer attached to follow-up responses.

Checkout API and Shop API plugin setup#

There’s a new section added to the Checkout API plugin config:

//a.storyblok.com/f/233206/87f7dc4779/recaptcha-checkout-api-plugin-settings.png

It allows for enabling selective protection of specific endpoints, which need to be secured from bot traffic.

A similar setup is there for Shop API, but only for endpoints directly changing a selection:

//a.storyblok.com/f/233206/44689157c8/recaptcha-shop-api-plugin-settings.png

Shop API doesn’t allow for direct calls from a browser, so captcha callback needs to be sent to a proxy (your backend for frontend), from where it would be passed to the Shop API’s POST captcha-result with the authorization header. There’s no additional logic required.

There will be no captcha section in Shop API’s selection responses and the protection will not work until you set the callback URL.

Validation flow#

The captcha.script from Centra contains two <script> tags. The first one is including the captcha code from the provider (it has async + defer attributes), and the other defines a callback that instantly calls the captcha logic, and then sends the result to the POST captcha-result endpoint. The endpoint accepts three parameters:

  • captchaToken - the result of captcha logic execution,
  • identifier - session token (Checkout API), or selection ID (Shop API),
  • pluginId - optional if there is only one active captcha plugin, but still recommended to include.

Centra then sends the captchaToken to the provider’s validation endpoint, which returns a validation status. The captcha-result finally responds with verified being either true or false, but also stores the result in user’s session. It is then reflected in the next selection responses.

The captcha script triggers a custom event centra_captcha_result when it gets the response. You can listen to it like this:

1 document.addEventListener("centra_captcha_result", handler);

Next, when a captcha-protected endpoint is reached, the stored verification result is checked before any other logic is executed. Missing or failed validation causes a 401 Unauthorized response with captcha: required error, and the same captcha section with the script to execute.

1 2 3 4 5 6 7 8 9 10 11 12 13 401 Unauthorized { "token": "c3a558c3aabcd95817098c3718a8d9ae", "errors": { "captcha": "required" }, "captcha": { "pluginId": 59, "type": "reCAPTCHA_v2", ... } }

Frontend side#

Captcha scripts can be executed right away, when they are seen in the response for the first time. But that’s just one possibility, the execution may be postponed to some later stage in order to avoid evaluating it for users, which would never reach the checkout. That’s why the captcha section contains all params necessary for the execution: captcha type, plugin ID, and the public (site) key. The captcha script can be executed at any time, and as soon as Centra receives a call to the captcha-result endpoint, the session/selection is authorized to access all protected endpoints.

In case of Checkout API it is required to send session token in both the request header, and as the identifier param in the body. Otherwise, a 406 Not Acceptable response is returned, because the identifiers don’t match. However, it is also acceptable to use the token-less mode sending Api-Token: none instead.

It’s crucial that the protection of API endpoints is enabled only after the frontend starts evaluating the captcha scripts, so it will not “just” work. It’s better to double-check the verification flow than accidentally block legitimate users' traffic.

Q&A#

  • What happens when there are more “Invisible Captcha” plugins active at the same time?

    They are both run, and if one of them has a positive verification, it will be selected. So it should be safe to rotate captcha secrets by setting up a new active plugin and then cancelling the old one, always keeping the endpoints protected.

  • What if the captcha plugin gets canceled, but the endpoint protection is still enabled?

    The protection stops working, and there are no 401 responses anymore.

  • Does captcha work with browser extensions blocking external tracking, ads, metrics, etc.?

    Yes, it should still work, captcha isn’t any of the above.

  • Doesn’t captcha negatively affect accessibility to a website, or the user experience in general?

    No, we make the captcha invisible and passive (if possible) so that there is no interaction required at all. Even if the security level is set to very high and a challenge is presented, the captcha provider has one or more solution for alternative verification methods so that it remains accessible to all.