Turnstile plugin
Show and validate a Cloudflare's Turnstile captcha
Usage
The following piece of code is the starting point to use the Turnstile plugin:
<html>
<head>
<link rel="stylesheet" href="/vendors/@form-validation/umd/styles/index.min.css" />
</head>
<body>
<form id="demoForm" method="POST">
...
<div id="captchaContainer"></div>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.3/es6-shim.min.js"></script>
<script src="/vendors/@form-validation/umd/bundle/popular.min.js"></script>
<script src="/vendors/@form-validation/umd/plugin-turnstile/index.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function(e) {
FormValidation.formValidation(
document.getElementById('demoForm'),
{
fields: {
...
},
plugins: {
...,
turnstile: new FormValidation.plugins.Turnstile({
element: 'captchaContainer',
message: ...,
siteKey: ...,
}),
},
}
);
});
</script>
</body>
</html>
The sample code above assumes that the FormValidation files are placed inside the vendors
directory. You might need to change the path depending on where you place them on the server.
Options
Option | Type | Description |
---|
backendVerificationUrl | String | The URL of your back-end that verifies the captcha via Turnstile API |
element * | String | The ID of element showing the captcha |
message * | String | The invalid message that will be shown in case the captcha is not valid |
siteKey * | String | The site key provided by Turnstile |
Bellow are the list of options provided by
TurnstileOption | Type | Description |
---|
action | String | A customer value that can be used to differentiate widgets under the same sitekey in analytics and which is returned upon validation |
appearance | String | Appearance controls when the widget is visible. It can be always (default), execute , or interaction-only |
cData | String | A customer payload that can be used to attach customer data to the challenge throughout its issuance and which is returned upon validation |
language | String | Language to display, must be either: auto (default) to use the language that the visitor has chosen, or an ISO 639-1 two-letter language code (e.g. en) or language and country code (e.g. en-US) |
refreshExpired | String | Automatically refreshes the token when it expires. Can take auto (default), manual or never |
retry | String | Controls whether the widget should automatically retry to obtain a token if it did not succeed. The default is auto , which will retry automatically. This can be set to never to disable retry upon failure |
retryInterval | number | When retry is set to auto , this controls the time between retry attempts in milliseconds. Value must be a positive integer less than 900000 , defaults to 8000 |
size | String | The widget size. Can take the following values: normal , compact |
tabIndex | number | The tabindex of Turnstile’s iframe for accessibility purposes. The default value is 0 |
theme | String | The widget theme. Can take the following values: light , dark , auto (default) |
Using the npm packages
If you are using a bundler such as
Webpack,
Rollup,
Parcel or
Vite, etc., to bundle
your application, then it's recommended to use the FormValidation NPM packages.
$ npm install @form-validation/bundle
$ npm install @form-validation/plugin-turnstile
- Import and use the Turnstile plugin:
import { formValidation } from '@form-validation/bundle/popular';
import { Turnstile } from '@form-validation/plugin-turnstile';
formValidation(
document.getElementById('demoForm'),
{
fields: {
...
},
plugins: {
turnstile: new Turnstile({
...
}),
...
},
}
);
Turnstile widget
The following form shows a Turnstile widget.
Invisible challenge
The following form shows an
invisible widget. In order to use it properly, remember to set the
appearance: 'execute'
option.
Back-end verification
If you want to take more steps of checking if the visitor on your site isn't a robot, then let's verify the captcha on the back-end side. You need to point the backendVerificationUrl
option to your back-end URL:
FormValidation.formValidation(
document.getElementById('demoForm'),
{
fields: {
...
},
plugins: {
...
turnstile: new FormValidation.plugins.Turnstile({
backendVerificationUrl: '/path/to/your/back-end/',
}),
},
}
);
When that option is enabled, the plugin will send an Ajax request with the value for
cf-turnstile-response
parameter. With the value of captcha and the Turnstile secret key, you can connect to
Turnstile verification URL to verify the captcha.
In order to inform user in case the captcha is valid or invalid, the back-end has to return a JSON encoded version of
{
"success": "true"
}
{
"success": "false"
}
The following code demonstrates how to do it in PHP, but you can do it with your favorite language.
<?php
$secretKey = '...';
$fields = array(
'secret' => $secretKey,
'response' => $_POST['cf-turnstile-response']
);
$postVars = '';
$sep = '';
foreach ($fields as $key => $value) {
$postVars .= $sep . urlencode($key) . '=' . urlencode($value);
$sep = '&';
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, 'https://challenges.cloudflare.com/turnstile/v0/siteverify');
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $postVars);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
header('Content-Type: application/json');
echo $result;
Changelog