PHPackages                             danieledesantis/laravel-cloudflare-turnstile-react-blade - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. danieledesantis/laravel-cloudflare-turnstile-react-blade

ActiveLibrary[Security](/categories/security)

danieledesantis/laravel-cloudflare-turnstile-react-blade
========================================================

Cloudflare Turnstile integration for Laravel with support for React, Inertia.js and Blade

1.0.0(5mo ago)13371MITPHPPHP ^8.1|^8.2|^8.3

Since Nov 26Pushed 5mo agoCompare

[ Source](https://github.com/danieledesantis/laravel-cloudflare-turnstile-react-blade)[ Packagist](https://packagist.org/packages/danieledesantis/laravel-cloudflare-turnstile-react-blade)[ RSS](/packages/danieledesantis-laravel-cloudflare-turnstile-react-blade/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (6)Versions (2)Used By (0)

Laravel Cloudflare Turnstile for React and Blade
================================================

[](#laravel-cloudflare-turnstile-for-react-and-blade)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d9e3c3b198a60fb2ba559bca178fb7357ff3ba5a77f4bfa7d2b6d3e61baed642/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f64616e69656c65646573616e7469732f6c61726176656c2d636c6f7564666c6172652d7475726e7374696c652d72656163742d626c6164652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/danieledesantis/laravel-cloudflare-turnstile-react-blade)[![Total Downloads](https://camo.githubusercontent.com/e866d90fec3653f5c0c593326e6b5d33eedc699810b60285a3ccd2d9197b7a04/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f64616e69656c65646573616e7469732f6c61726176656c2d636c6f7564666c6172652d7475726e7374696c652d72656163742d626c6164652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/danieledesantis/laravel-cloudflare-turnstile-react-blade)

Cloudflare Turnstile integration for Laravel with built-in support for Blade, React, and Inertia.js. Protect your Laravel applications from bots and abuse with Cloudflare's free CAPTCHA alternative.

Quickstart
----------

[](#quickstart)

Read the **[Quick Start Guide](QUICKSTART.md)** to get up and running in 5 minutes.

Features
--------

[](#features)

- **Easy Integration** - Drop-in Blade components and React hooks
- **Multiple Frameworks** - Support for Blade, React and Inertia.js
- **Secure** - Server-side validation with customizable rules
- **Testable** - Built-in testing mode for automated tests
- **Configurable** - Extensive configuration options
- **Middleware Support** - Protect routes with middleware
- **Validation Rules** - Custom Laravel validation rules
- **IP Whitelisting** - Skip verification for trusted IPs

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.x or higher
- A Cloudflare Turnstile site key and secret key

Installation
------------

[](#installation)

### Step 1: Install via Composer

[](#step-1-install-via-composer)

```
composer require danieledesantis/laravel-cloudflare-turnstile-react-blade
```

### Step 2: Publish Configuration

[](#step-2-publish-configuration)

```
php artisan vendor:publish --tag=turnstile-config
```

### Step 3: Publish Components

[](#step-3-publish-components)

#### Publish React/TypeScript Components (for React/Inertia.js projects)

[](#publish-reacttypescript-components-for-reactinertiajs-projects)

If you are using React or Inertia.js, publish the TypeScript components:

```
php artisan vendor:publish --tag=turnstile-components
```

This will publish the components to `resources/js/Components/Turnstile/`:

- `hooks/useTurnstile.tsx` - React hook for Turnstile
- `components/Turnstile.tsx` - React component for Turnstile
- `index.ts` - Exports

You can then import them directly in your code:

```
import { useTurnstile, Turnstile } from '@/Components/Turnstile';
```

#### Publish Blade Components (for Blade projects)

[](#publish-blade-components-for-blade-projects)

If you are using the Blade templating engine, publish the component:

```
php artisan vendor:publish --tag=turnstile-views
```

This will publish the component to `resources/views/vendor/turnstile/components/turnstile-widget.blade.php`.

You can now use it in your code:

```

```

### Step 4: Configure Environment Variables

[](#step-4-configure-environment-variables)

Add your Cloudflare Turnstile credentials to your `.env` file:

```
TURNSTILE_SITEKEY=your-site-key
TURNSTILE_SECRETKEY=your-secret-key
```

Get your keys from [Cloudflare Dashboard](https://dash.cloudflare.com/?to=/:account/turnstile).

1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com/)
2. Navigate to **Turnstile** in the sidebar
3. Click **Add Site**
4. Enter your domain name
5. Choose widget mode (recommended: **Managed**)
6. Copy your **Site Key** and **Secret Key**

Usage
-----

[](#usage)

### Step 1: Add Laravel Validation

[](#step-1-add-laravel-validation)

You can add Laravel validation for the Cloudflare Turnstile response using one of the following methods:

#### Using the Validation Rule

[](#using-the-validation-rule)

```
use DanieleDeSantis\LaravelTurnstile\Http\Rules\TurnstileValidation;

public function store(Request $request)
{
    $request->validate([
        'email' => 'required|email',
        'password' => 'required',
        'cf-turnstile-response' => ['required', new TurnstileValidation()],
    ]);

    // Your logic here
}
```

#### Using the Facade

[](#using-the-facade)

```
use DanieleDeSantis\LaravelTurnstile\Facades\Turnstile;

public function store(Request $request)
{
    try {
        Turnstile::verify(
            $request->input('cf-turnstile-response'),
            $request->ip()
        );

        // Verification successful
    } catch (\Exception $e) {
        return back()->withErrors(['turnstile' => $e->getMessage()]);
    }
}
```

#### Middleware

[](#middleware)

Protect entire routes or route groups:

```
use DanieleDeSantis\LaravelTurnstile\Http\Middleware\VerifyTurnstile;

// In routes/web.php
Route::post('/contact', [ContactController::class, 'store'])
    ->middleware('turnstile');

// With custom token field
Route::post('/register', [RegisterController::class, 'store'])
    ->middleware('turnstile:captcha-token');
```

### Step 2: Add Cloudflare Turnstile widget to the frontend

[](#step-2-add-cloudflare-turnstile-widget-to-the-frontend)

#### React / Inertia.js

[](#react--inertiajs)

Publish the React components using

```
php artisan vendor:publish --tag=turnstile-components
```

Pass the sitekey to your component

```
return Inertia::render('Auth/Login', [
    'turnstile_sitekey' => config('turnstile.sitekey'),
]);
```

Add the widget to you form using one of the following methods:

##### Using the React Component

[](#using-the-react-component)

```
import { Turnstile } from '@/Components/Turnstile';
import { useForm } from '@inertiajs/react';

export default function LoginForm({ turnstile_sitekey }) {
    const { data, setData, post, processing, errors } = useForm({
        // Your form fields
        'cf-turnstile-response': '',
    });

    const submit = e => {
        e.preventDefault();
        post(route('login'));
    };

    return (

            {/* Your form fields */}

             setData('cf-turnstile-response', token)}
                onError={() => setData('cf-turnstile-response', '')}
                onExpire={() => setData('cf-turnstile-response', '')}
                theme='auto'
                size='normal'
            />

            Login

    );
}
```

##### Using the React Hook

[](#using-the-react-hook)

```
import { useTurnstile } from '@/Components/Turnstile';
import { useForm } from '@inertiajs/react';

export default function LoginForm({ turnstile_sitekey }) {
    const { data, setData, post } = useForm({
        // Your form fields
        'cf-turnstile-response': '',
    });

    const { turnstileRef } = useTurnstile({
        sitekey: turnstile_sitekey,
        onSuccess: (token: string) => setData('cf-turnstile-response', token),
        onError: () => setData('cf-turnstile-response', ''),
        onExpire: () => setData('cf-turnstile-response', ''),
    });

    const submit = e => {
        e.preventDefault();
        post(route('login'));
    };

    return (

            {/* Your form fields */}

            Login

    );
}
```

##### TypeScript Types

[](#typescript-types)

The package includes full TypeScript support:

```
interface Window {
    turnstile?: {
        render: (element: HTMLElement, options: TurnstileOptions) => string;
        reset: (widgetId: string) => void;
        remove: (widgetId: string) => void;
    };
}
```

#### Blade Components

[](#blade-components)

Publish the Blade components using

```
php artisan vendor:publish --tag=turnstile-views
```

Add the component to your forms:

```

    @csrf

    Login

```

##### Customizing the Widget

[](#customizing-the-widget)

```

```

Available options:

- `theme`: `auto`, `light`, or `dark` (default: `auto`)
- `size`: `normal`, `compact`, or `flexible` (default: `normal`)
- `field-name`: Custom field name (default: `cf-turnstile-response`)
- `callback`: JavaScript callback function name
- `error-callback`: Error callback function name
- `expired-callback`: Expired callback function name

Configuration
-------------

[](#configuration)

The configuration file `config/turnstile.php` provides extensive customization:

```
return [
    // Enable/disable Turnstile globally
    'enabled' => env('TURNSTILE_ENABLED', true),

    // Your Cloudflare credentials
    'sitekey' => env('TURNSTILE_SITEKEY', ''),
    'secretkey' => env('TURNSTILE_SECRETKEY', ''),

    // Verification endpoint
    'endpoint' => 'https://challenges.cloudflare.com/turnstile/v0/siteverify',

    // Request timeout in seconds
    'timeout' => 10,

    // Custom error messages
    'error_messages' => [
        'verification_failed' => 'The security verification failed. Please try again.',
        'missing_token' => 'Security verification is required.',
        'timeout' => 'Security verification timed out. Please try again.',
    ],

    // Testing mode (bypasses verification)
    'testing' => env('TURNSTILE_TESTING', env('APP_ENV') === 'testing'),

    // Skip verification for these IPs
    'skip_ips' => [],

    // Widget appearance
    'theme' => 'auto', // auto, light, dark
    'size' => 'normal', // normal, compact, flexible
];
```

Testing
-------

[](#testing)

The package automatically bypasses Turnstile verification when `APP_ENV=testing` or `TURNSTILE_TESTING=true`.

### In Your Tests

[](#in-your-tests)

```
use DanieleDeSantis\LaravelTurnstile\Facades\Turnstile;

class LoginTest extends TestCase
{
    public function test_user_can_login()
    {
        // Turnstile is automatically disabled in testing
        $response = $this->post('/login', [
            'email' => 'test@example.com',
            'password' => 'password',
            'cf-turnstile-response' => 'test-token', // Any value works
        ]);

        $response->assertRedirect('/dashboard');
    }

    public function test_turnstile_verification()
    {
        // Enable verification for specific tests
        Turnstile::disableTesting();

        // Your test logic

        // Re-enable testing mode
        Turnstile::enableTesting();
    }
}
```

### Running Package Tests

[](#running-package-tests)

```
composer install
./vendor/bin/phpunit
```

Advanced Usage
--------------

[](#advanced-usage)

### Programmatic Verification

[](#programmatic-verification)

```
use DanieleDeSantis\LaravelTurnstile\Facades\Turnstile;

// Check if Turnstile is enabled
if (Turnstile::isEnabled()) {
    // Get the site key
    $siteKey = Turnstile::getSiteKey();
}

// Verify a token
try {
    $verified = Turnstile::verify($token, $ipAddress);
} catch (TurnstileVerificationException $e) {
    // Handle verification failure
    $errorCodes = $e->getErrorCodes();
}
```

### IP Whitelisting

[](#ip-whitelisting)

Skip verification for trusted IPs (useful for local development):

```
TURNSTILE_SKIP_IPS=127.0.0.1,192.168.1.100
```

Or in `config/turnstile.php`:

```
'skip_ips' => ['127.0.0.1', '::1'],
```

### Custom Error Messages

[](#custom-error-messages)

Customize error messages in `config/turnstile.php`:

```
'error_messages' => [
    'verification_failed' => 'Custom verification failed message',
    'missing_token' => 'Custom missing token message',
    'timeout' => 'Custom timeout message',
],
```

### Controller Example (Complete)

[](#controller-example-complete)

```
