Skip to content

Integrate Turnstile, WAF, & Bot Management

Last reviewed: 2 months ago

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.

Overview

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:

  • WAF filters malicious traffic based on network signals.
  • Bot Management analyzes requests to identify and mitigate automated threats.
  • Turnstile examines client-side and browser signals to distinguish between human users and bots.

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.

Before you begin

  • You must have a Cloudflare account with access to WAF and Bot Management (if using).
  • An existing JavaScript/TypeScript-based route handling authentication.

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.

Configure WAF and Bot Management

If your site is on Cloudflare's network and subscribed to an Enterprise plan, you must configure WAF and Bot Management.

Issue challenges for potential bot traffic

  1. Log in to the Cloudflare dashboard and select your account.
  2. Go to Security > WAF.
  3. Create a new custom WAF rule by selecting "Edit expression":
    • Field: "Bot Score"
      • Operator: "less than or equal to"
      • Value: "30"
    • Action: "Managed Challenge"

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.

Set up Cloudflare Turnstile

Turnstile can be used on any site, regardless of whether it is on Cloudflare's network:

  1. Log in to the Cloudflare dashboard and select your account.
  2. Go to Security > Turnstile.
  3. Select Add widget and fill out the necessary information.
  4. Add your domain to the Turnstile configuration.
  5. 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.

Integrate Turnstile into your application

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 login form

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" 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.

Handle the login request

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.

Testing

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:

  1. Add a WAF rule that always forwards your IP address to the challenge page.
  2. Add a WAF rule that checks for the presence of a query parameter, such as ?challenge=true.

Best practices

  1. Always validate the Turnstile token on the server-side before checking credentials.
  2. Use environment variables to store sensitive information like your Turnstile secret key.
  3. Implement proper error handling and logging to monitor for potential security issues.

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.

Resources

If you are interested in customizing Turnstile, refer to the resources below for more information:

  • Client-side rendering. Learn how to customize how and when Turnstile renders in your user interface, to better fit your application's needs and user experience.
  • Server-side validation. Learn how Turnstile's API works, including request parameters, as well as how to handle different types of responses, including error codes.
  • Turnstile Analytics. Learn how to view Turnstile's analytics in the Cloudflare dashboard. This includes metrics on the number of challenges issued, as well as the CSR (Challenge Solve Rate).