Providers
Cloudflare Turnstile (turnstile)
Widget options: action, cData, theme (auto, light, dark), size (normal, flexible, compact), language, appearance (always, execute, interaction-only), execution (render, execute), tabindex, retry, retryInterval, refreshExpired, refreshTimeout, feedbackEnabled, and the callbacks callback, errorCallback, expiredCallback, timeoutCallback, beforeInteractiveCallback, afterInteractiveCallback, unsupportedCallback (names of global functions). They are rendered as the data-* attributes.
actionis at most 32 characters andcDataat most 255 characters (alphanumeric,_and-). Whenactionis configured, the action in the verify response must match it.- Tokens are at most 2048 characters, valid for 300 seconds, and can be verified once. Longer tokens are rejected without a request.
- Every verify request carries an
idempotency_key(a UUID), soretrycan resend the same request safely.
Google reCAPTCHA v2 (recaptcha_v2)
Renders the "I'm not a robot" checkbox. Widget options: theme (light, dark), size (normal, compact), tabindex, callback, expiredCallback, errorCallback. language is sent as the hl script parameter. The response does not contain the action, so action is not checked. The invisible reCAPTCHA (size invisible) needs your own JavaScript to call grecaptcha.execute().
Where www.google.com is not accessible, set scriptUrl to https://www.recaptcha.net/recaptcha/api.js and verifyUrl to https://www.recaptcha.net/recaptcha/api/siteverify.
Google reCAPTCHA v3 (recaptcha_v3)
reCAPTCHA v3 has no widget. widget() renders a hidden g-recaptcha-response input and a small script. When the form is submitted, the script calls grecaptcha.execute() with the action, stores the token in the input and submits the form again (keeping the clicked submit button). Tokens are fetched on submit because they expire after two minutes.
echo $this->Captcha->widget(['action' => 'contact']);public $components = ['Captcha.Captcha' => ['actions' => ['add'], 'action' => 'contact', 'scoreThreshold' => 0.7]];actiondefaults tosubmit. It may contain alphanumeric characters,/and_. The action in the verify response must match the configured action, so configure the same action in the component as in the widget.scoreThresholddefaults to0.5. A response without a score or with a lower score fails withscore-too-low. Read the score with$this->Captcha->getResult()->getScore(), e.g. to require additional verification instead of rejecting the request. SetscoreThresholdtofalseto make the decision yourself.
hCaptcha (hcaptcha)
Widget options: theme (light, dark), size (normal, compact), tabindex, callback, expiredCallback, chalexpiredCallback, openCallback, closeCallback, errorCallback. language is sent as the hl script parameter.
- The site key is sent to the verify endpoint (
sitekey), as hCaptcha recommends, so tokens issued for another site key are rejected. - The hCaptcha script also adds
g-recaptcha-responseunless it is loaded withrecaptchacompat=off:$this->Captcha->widget(['script' => ['query' => ['recaptchacompat' => 'off']]]). - The hCaptcha Enterprise
scoreis not checked (a higher hCaptcha score means a more likely bot). Read it withgetResult()->getScore().
Custom Providers
Set provider to a class that implements CaptchaProviderInterface. Extending BaseCaptchaProvider gives you the common behaviour:
// src/Lib/MyCaptchaProvider.php (legacy layout: app/Lib/MyCaptchaProvider.php)
App::uses('BaseCaptchaProvider', 'Captcha.Lib/Provider');
class MyCaptchaProvider extends BaseCaptchaProvider
{
protected string $defaultScriptUrl = 'https://captcha.example.com/api.js';
protected string $defaultVerifyUrl = 'https://captcha.example.com/siteverify';
protected string $widgetClass = 'my-captcha';
protected string $field = 'my-captcha-response';
protected array $widgetOptions = ['theme' => 'data-theme'];
public function name(): string
{
return 'my_captcha';
}
}Configure::write('Captcha.provider', 'MyCaptchaProvider'); // or 'MyPlugin.MyCaptchaProvider'The class is loaded with App::uses() from Lib (or the plugin's Lib) unless it is already loaded. It is constructed with the merged configuration array.
References
- Cloudflare Turnstile: client-side rendering, widget configurations, server-side validation, testing, Content Security Policy
- Google reCAPTCHA: v2 checkbox, v3, verifying the user's response, FAQ (test keys, CSP)
- hCaptcha: developer guide, configuration
