laravel-cloudflare-turnstile

repository·main·Indexed 19 days ago

https://github.com/ryangjchandler/laravel-cloudflare-turnstile

A Laravel package for integrating Cloudflare Turnstile bot protection. It provides Blade components (<x-turnstile.scripts /> and <x-turnstile />) for the frontend, a Turnstile validation rule for the backend, and a Turnstile facade for verifying response tokens via the Cloudflare API. The package supports Livewire via wire:model and includes testing utilities such as Turnstile::fake() and Turnstile::dummy().

Tokens
3.3K
Snippets
20
Records
21
Agent score
61%

What's inside laravel-cloudflare-turnstile

  1. Note on `Client` lifecycle changes in 3.0

    main
    In version 3.0, the Client class has changed from a singleton to a scoped singleton. This change was implemented to ensure compatibility with Laravel Octane and other single-boot lifecycles. If you interact with the Client manually, verify that your application logic remains correct under this new lifecycle model.
  2. Replace `@turnstileScripts` with the Blade component

    main

    In version 3.0, the @turnstileScripts directive has been removed. To include the necessary Cloudflare Turnstile scripts in your Blade templates, use the <x-turnstile.scripts /> Blade component instead.

    {{-- Old way (2.x) --}}
    @turnstileScripts
    
    {{-- New way (3.0+) --}}
    <x-turnstile.scripts />
  3. Display Turnstile widgets in Blade

    main

    To use Turnstile, you must first include the necessary scripts in your layout's <head> using the <x-turnstile.scripts> component.

    Then, place the <x-turnstile /> component inside your <form> to render the widget. The component automatically uses your configured site key.

    {{-- In your layout file --}}
    <html>
        <head>
            <x-turnstile.scripts />
        </head>
        <body>
            {{ $slot }}
        </body>
    </html>
    
    {{-- In your form --}}
    <form action="/" method="POST">
        <x-turnstile />
        <button>Submit</button>
    </form>
  4. Use Turnstile with Livewire

    main

    The package supports Livewire via wire:model.

    Multiple Widgets: If you have more than one widget on a single page, you must provide a unique id to each <x-turnstile /> component. The ID must match the following regular expression: /^[a-zA-Z_][a-zA-Z0-9_-]*$/. Failure to provide a valid ID will trigger an exception.

    {{-- Single widget --}}
    <x-turnstile wire:model="yourModel" />
    
    {{-- Multiple widgets require unique IDs --}}
    <x-turnstile id="my_widget" wire:model="captcha" />
  5. Use the `Turnstile` rule object instead of the `turnstile` string or macro

    main

    In version 3.0, the string-based validation rule 'turnstile' and the Rule::turnstile() macro have been removed. You must now use an instance of the RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile class for validation.

    use RyanChandler\
    LaravelCloudflareTurnstile\Rules\Turnstile;
    
    $request->validate([
        'cf-turnstile-response' => [
            'required',
            new Turnstile, 
        ]
    ]);
  6. Configure Turnstile credentials

    main

    After installation, add the turnstile configuration array to your config/services.php file. This maps the configuration to environment variables.

    Then, add your Cloudflare Turnstile keys to your .env file using the following keys:

    • TURNSTILE_SITE_KEY
    • TURNSTILE_SECRET_KEY
    // config/services.php
    return [
        // ...,
        'turnstile' => [
            'key' => env('TURNSTILE_SITE_KEY'),
            'secret' => env('TURNSTILE_SECRET_KEY'),
        ],
    ];
    TURNSTILE_SITE_KEY="1x00000000000000000000AA"
    TURNSTILE_SECRET_KEY="2x0000000000000000000000000000000AA"
  7. Understand the SiteverifyResponse object

    main

    The SiteverifyResponse class represents the result of a Cloudflare Turnstile verification attempt. It is used to determine if a Turnstile token is valid.

    It contains two primary properties:

    • success: A boolean indicating if the verification was successful.
    • errorCodes: An array of error strings returned by Cloudflare if success is false.

    You can instantiate this object using the static factory methods success() or failure().

    // Example of a successful response
    $response = SiteverifyResponse::success();
    
    // Example of a failed response with error codes
    $response = SiteverifyResponse::failure(['invalid-input-response']);
  8. Customize the Turnstile widget attributes

    main

    You can pass standard Cloudflare Turnstile configuration attributes directly to the <x-turnstile /> component using the data-* prefix. Common attributes include data-theme, data-action, and various callback handlers.

    <x-turnstile
        data-action="login"
        data-cdata="sessionid-123456789"
        data-callback="callback"
        data-expired-callback="expiredCallback"
        data-error-callback="errorCallback"
        data-theme="dark"
        data-tabindex="1"
    />
  9. Fake Turnstile responses in tests

    main

    Use the Turnstile facade to mock Turnstile behavior in your test suite. This allows you to simulate successful, failed, or expired token scenarios without making real network requests.

    To generate a valid-looking dummy token for form submissions in tests, use Turnstile::dummy().

    use RyanChandler\LaravelCloudflareTurnstile\Facades\Turnstile;
    
    // Force a successful response
    Turnstile::fake();
    
    // Force a failed response
    Turnstile::fake()->fail();
    
    // Force an expired token response
    Turnstile::fake()->expired();
    
    // Using a dummy token in a test request
    post('/my-form', [
        'cf-turnstile-response' => Turnstile::dummy(),
    ]);
  10. Validate Turnstile responses in Laravel

    main

    To verify the Turnstile response on the server side, use the Turnstile validation rule. The response token is sent in the cf-turnstile-response field.

    use RyanChandler\
    LaravelCloudflareTurnstile\Rules\Turnstile;
    
    public function submit(Request $request)
    {
        $request->validate([
            'cf-turnstile-response' => ['required', new Turnstile],
        ]);
    }