Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions src/content/docs/turnstile/tutorials/login-pages.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Protect your login pages
title: Protect your forms
pcx_content_type: tutorial
updated: 2024-07-09
updated: 2025-05-30
difficulty: Beginner
languages:
- JavaScript
Expand All @@ -12,12 +12,12 @@ sidebar:

---

This tutorial will guide you through integrating Cloudflare Turnstile to protect your login page. Learn how to implement the Turnstile widget on the client side and verify the Turnstile token via the siteverify API on the server side.
This tutorial will guide you through integrating Cloudflare Turnstile to protect your web forms, such as login, signup, or contact forms. Learn how to implement the Turnstile widget on the client side and verify the Turnstile token via the siteverify API on the server side.

## Before you begin

- You must have a Cloudflare account.
- You must have a web application with a login or signup page.
- You must have a web application with a form you want to protect.
- You must have basic knowledge of HTML and your server-side language of choice, such as Node.js or Python.

## Get Your Turnstile sitekey and secret key
Expand All @@ -28,26 +28,34 @@ This tutorial will guide you through integrating Cloudflare Turnstile to protect

## Add the Turnstile widget to your HTML form

1. Add the Turnstile widget to your login form.
1. Add the Turnstile widget to your form.
2. Replace `YOUR-SITE-KEY` with the sitekey from Cloudflare.
3. Add a `data-callback` attribute to the Turnstile widget div. This JavaScript function will be called when the challenge is successful.
4. Ensure your submit button is initially disabled.

```html title="Example" {13-14}
```html title="Example" {14-15,17}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login Page</title>
<title>Contact Form</title>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script>
function enableSubmit() {
document.getElementById("submit-button").disabled = false;
}
</script>
</head>
<body>
<form id="login-form" action="/login" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<form id="contact-form" action="/submit" method="POST">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email" required>
<textarea name="message" placeholder="Message" required></textarea>

<!-- Turnstile widget -->
<div class="cf-turnstile" data-sitekey="YOUR-SITE-KEY"></div>
<div class="cf-turnstile" data-sitekey="YOUR-SITE-KEY" data-callback="enableSubmit"></div>

<button type="submit">Log in</button>
<button type="submit" id="submit-button" disabled>Submit</button>
</form>
</body>
</html>
Expand All @@ -65,7 +73,7 @@ const app = express();

app.use(bodyParser.urlencoded({ extended: true }));

app.post('/login', async (req, res) => {
app.post('/submit', async (req, res) => {
const turnstileToken = req.body['cf-turnstile-response'];
const secretKey = 'your-secret-key';

Expand All @@ -78,11 +86,12 @@ app.post('/login', async (req, res) => {
});

if (response.data.success) {
// Token is valid, proceed with login
const username = req.body.username;
const password = req.body.password;
// Your login logic here
res.send('Login successful');
// Token is valid, proceed with form submission
const name = req.body.name;
const email = req.body.email;
const message = req.body.message;
// Your form processing logic here
res.send('Form submission successful');
} else {
res.status(400).send('Turnstile verification failed');
}
Expand All @@ -100,13 +109,13 @@ app.listen(3000, () => {

It is crucial to handle the verification of the Turnstile token correctly. This section covers some key points to keep in mind.

### Verify the token after credentials input
### Verify the token after form input

- Ensure that you verify the Turnstile token after the user has put in their credentials and selected **log in** to your website or application.
- If you verify the token before the user inputs their credentials, a malicious visitor could bypass the protection by reentering the login credentials.
- Ensure that you verify the Turnstile token after the user has filled out the form and selected **submit**.
- If you verify the token before the user inputs their data, a malicious actor could potentially bypass the protection by manipulating the form submission after obtaining a valid token.

### Proper flow implementation

- When the user submits the login form, send both the login credentials and the Turnstile token to your server.
- When the user submits the form, send both the form data and the Turnstile token to your server.
- On the server side, verify the Turnstile token first.
- Based on the verification response, decide whether to proceed with checking the login credentials.
- Based on the verification response, decide whether to proceed with processing the form data.
Loading