| [ Web Proxy ] |
| Viewing: https://developers.cloudflare.com/turnstile/tutorials/integrating-turnstile-waf-and-bot-management/ | [Back] [Original] |
This tutorial will guide you on how to integrate Cloudflare Turnstile, Web Application Firewall (WAF), and Bot Management into an existing authentication system. This combination creates a robust defense against various threats, including automated attacks and malicious login attempts.
To use WAF and Bot Management, your site must have its DNS pointing through Cloudflare. However, Turnstile can be used independently on any site including those not on Cloudflare's network. This tutorial will cover how to implement all three products, but you can focus on Turnstile if your site is not on Cloudflare's network.
WAF, Bot Management, and Turnstile work well together by operating on different layers of the application:
By combining server-side (WAF and Bot Management) and client-side (Turnstile) security measures, you can combine multiple layers of defense to create a protection system that is difficult for attackers to circumvent.
This tutorial uses a simple login form written in plain HTML to demonstrate how to integrate Turnstile into your application. In the backend, a stubbed out authentication route, written in TypeScript, will handle the login request. You may replace this with the language of your choice. As long as your language or framework is able to make an external HTTP request to Turnstile's API, you can integrate Turnstile into your application.
If your site is on Cloudflare's network and subscribed to an Enterprise plan, you must configure WAF and Bot Management.
In the Cloudflare dashboard, go to the WAF page.
Go to WAF ↗Create a new custom WAF rule by selecting Edit expression:
This configuration challenges requests with a low bot score, leveraging network signals to identify potential threats before they reach your application. You may customize the score threshold based on your specific use case.
Turnstile can be used on any site, regardless of whether it is on Cloudflare's network:
In the Cloudflare dashboard, go to the Turnstile page.
Go to Turnstile ↗Select Add widget and fill out the necessary information.
Add your domain to the Turnstile configuration.
Select Create.
Turnstile adds an extra layer of security by analyzing browser and client-side signals, complementing the server-side checks performed by WAF and Bot Management.
If your site is on Cloudflare, you can enable the option to use the existing clearance cookie in Turnstile's settings. This integration allows Turnstile to use the clearance cookie as part of its determination of whether a user should receive a challenge. This integration is optional, but recommended if you already are using WAF and Bot Management.
There are two components to implementing Turnstile into your application: the Turnstile widget and the server-side validation logic.
Add the Turnstile widget to your existing login form:
<form id="login-form">
<input type="text" id="username" placeholder="Username" required />
<input type="password" id="password" placeholder="Password" autocomplete="off" required />
<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>
<button type="submit">Log in</button>
</form>
<script
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
async
defer
></script>
Replace <YOUR-SITE-KEY> with your actual Turnstile site key.
In your existing authentication route, add Turnstile validation:
async function validateTurnstileToken(
ip: string,
token: string,
secret: string,
): Promise<boolean> {
const response = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ip, secret, response: token }),
},
);
const outcome = await response.json();
return outcome.success;
}
// Assume that this is a TypeScript route handler.
// You may replace this with a different implementation,
// based on your language or framework
export async function onRequestPost(context) {
const { request, env } = context;
const { username, password, token } = await request.json();
// Validate Turnstile token
const secretKey = env.TURNSTILE_SECRET_KEY;
const ip = request.headers.get("CF-Connecting-IP");
const turnstileValid = await validateTurnstileToken(ip, token, secretKey);
if (!turnstileValid) {
// Return back to the login page with an error message
return Response.redirect("/login", 302, {
headers: {
Location: "/login?error=invalid-turnstile-token",
},
});
}
// Perform your existing authentication logic here
const isValidLogin = await checkCredentials(username, password);
if (isValidLogin) {
return new Response(JSON.stringify({ message: "Login successful" }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
} else {
return new Response(JSON.stringify({ error: "Invalid credentials" }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
}
async function checkCredentials(
username: string,
password: string,
): Promise<boolean> {
// Your existing credential checking logic
}
This setup ensures that the Turnstile token is validated on the server-side before proceeding with the login process, adding an extra layer of security based on client-side signals.
After deployment, you will want to test your integration. Because your bot score will be low, you will probably not receive a challenge. However, you can add additional rules as needed to force a redirect to the challenge page. Some options to do this are:
?challenge=true.By combining Turnstile with WAF and Bot Management, you can create a system that secures your application at the network layer, while also providing an extra layer of protection using client-side signals. This approach makes it significantly more difficult for malicious actors to automate attacks against your login system.
If you are interested in customizing Turnstile, refer to the resources below for more information:
| Web Proxy Viewer | New URL | Original Page |