Cloudflare Turnstile Workers Demo

repository·main·Indexed 42 days ago

https://github.com/cloudflare/turnstile-demo-workers

A demonstration project for implementing Cloudflare Turnstile protection in Cloudflare Workers. It covers implicit and explicit rendering methods, token validation via the siteverify endpoint, and handling requests within a Worker fetch handler.

Tokens
1.1K
Snippets
5
Records
5
Agent score
4%

What's inside Cloudflare Turnstile

  1. Validate Turnstile tokens in a Cloudflare Worker

    main

    To validate a Cloudflare Turnstile token within a Worker, you must extract the cf-turnstile-response token from the incoming POST request's formData. You then perform a POST request to the Cloudflare Turnstile verification endpoint (https://challenges.cloudflare.com/turnstile/v0/siteverify) using FormData.

    Required fields for the verification request:

    • secret: Your Turnstile secret key.
    • response: The token provided by the Turnstile widget (cf-turnstile-response).
    • remoteip: The user's IP address (typically retrieved from the CF-Connecting-IP header).

    If the response JSON contains success: false, the token is invalid.

    async function handlePost(request) {
        const body = await request.formData();
        const token = body.get('cf-turnstile-response');
        const ip = request.headers.get('CF-Connecting-IP');
    
        let formData = new FormData();
        formData.append('secret', 'YOUR_SECRET_KEY');
        formData.append('response', token);
        formData.append('remoteip', ip);
    
        const result = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
            body: formData,
            method: 'POST',
        });
    
        const outcome = await result.json();
        if (!outcome.success) {
            return new Response('The provided Turnstile token was not valid! \n' + JSON.stringify(outcome));
        }
    
        return new Response('Turnstile token successfuly validated. \n' + JSON.stringify(outcome));
    }
  2. Implement the Turnstile Worker fetch handler

    main

    The demo uses a default export object with a fetch method to handle incoming requests. It routes traffic based on the HTTP method and URL path:

    1. POST requests: Handled by a logic block (like handlePost) that validates the Turnstile token.
    2. GET requests:
      • /explicit: Serves HTML content rendered with explicit Turnstile configuration.
      • All other paths: Serves HTML content rendered with implicit Turnstile configuration.

    All HTML responses are returned with the Content-Type: text/html header.

    export default {
        async fetch(request) {
            if (request.method === 'POST') {
                return await handlePost(request);
            }
    
            const url = new URL(request.url);
            let body = implicitRenderHtml;
            if (url.pathname === '/explicit') {
                body = explicitRenderHtml;
            }
    
            return new Response(body, {
                headers: {
                    'Content-Type': 'text/html',
                },
            });
        },
    };