Turnstile CAPTCHA
Javascript
Head over to the official Turnstile documentation to read more about how to integrate Cloudflare's CAPTCHA solution.
Insert the Turnstile script snippet in your HTML’s <head>
element:
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
Configuration
Within your Cloudflare account under Turnstile create a new Site and get the site key and site secret. Set both in your .env
file.
TURNSTILE_SITE_KEY=sitekey
TURNSTILE_SECRET_KEY=sitesecret
Alternatively you could use thebnomei.kart.turnstile.sitekey
andbnomei.kart.turnstile.secretkey
config options. But using the.env
file is safer.
Widget
Render the Turnstile widget with the code from the documentation or use the following snippet kart/turnstile-widget
.
<?php snippet('kart/turnstile-widget') ?>
Securing Forms
It might suffice to only secure routes accessible before the user is logged in, like the Login- and Register/Sign-Up-Forms. That is assuming bots do not create valid logins.
Use the code from the documentation or the following snippet kart/turnstile-form
.
<form action="<?= kart()->urls()->magiclink() ?>" method="POST">
<label>
<input type="email" name="email" required
placeholder="<?= t('email') ?>" autocomplete="email"
value="<?= urldecode(get('email', '')) ?>">
</label>
<?php snippet('kart/turnstile-form') ?>
<input type="hidden" name="redirect" value="<?= url('kart/login') ?>?status=sent">
<input type="hidden" name="success_url" value="<?= url('kart') ?>?msg=Welcome%20back">
<button type="submit"><?= t('login') ?> <?= t('link') ?></button>
</form>
Behind the Scenes
The endpoints intended for public use, which are most likely targeted by bots (login, register/signup, magic-link), are preconfigured with a check for the Turnstile token.
If posted with the form the \Bnomei\Kart\Router::denied()
-helper will query the https://challenges.cloudflare.com/turnstile/v0/siteverify
endpoint with your secretkey
and check if the form request is legit or not.
On success, the form will continue as intended. If not, it will redirect to the error page or yield a 401
HTTP status code.