---
title: "Aggiungere Google ReCaptcha V3 a login Laravel Filament"
id: "182"
type: "post"
slug: "aggiungere-google-recaptcha-v3-a-login-laravel-filament"
published_at: "2026-04-20T15:47:51+00:00"
modified_at: "2026-05-26T09:36:46+00:00"
url: "https://pierluigipapeschi.com/aggiungere-google-recaptcha-v3-a-login-laravel-filament/"
markdown_url: "https://pierluigipapeschi.com/aggiungere-google-recaptcha-v3-a-login-laravel-filament.md"
excerpt: "Proteggere la pagina di login di un sito è diventato a dir poco indispensabile. Il sistema di Google, il Recaptcha ha 2 versioni: la V2 che prevede l’interazione dell’utente flaggando un checkbox e la V3 che si basa su un..."
taxonomy_category:
  - "FilamentPHP"
  - "Google"
  - "Laravel"
---

Proteggere la pagina di login di un sito è diventato a dir poco indispensabile. Il sistema di Google, il Recaptcha ha 2 versioni: la V2 che prevede l’interazione dell’utente flaggando un checkbox e la V3 che si basa su un punteggio che “lui” fa per capire se sei umano o un bot.

Noi ci concentriamo sulla versione 3 e lo andremo ad aggiungere alla pagina di login di un sito Laravel 13 con FilamentPHP V5 per la gestione del backend.

## Recaptcha V3

Per prima cosa dobbiamo recuperare le chiavi SITE_KEY e SECRET che si creano accedendo alla console di amministrazione di recaptcha: [https://www.google.com/recaptcha/admin/create?hl=it](https://www.google.com/recaptcha/admin/create?hl=it)

Fatto questo salviamole nel file .env del progetto Laravel (vedi [questo articolo](https://pierluigipapeschi.com/realizzare-un-progetto-laravel-filament-reactjs-tailwindcss/)
).

```
RECAPTCHA_SITE_KEY=6LfcG...
RECAPTCHA_SECRET=6LfcG...
```

Dopodiché puliamo la cache dei parametri di ambiente con il comando `php artisan config:cache`

Nel file services.php persente dentro la cartella config, mettiamo in fondo (prima della chiusura dell’array):

```
'recaptcha' => [
    'site_key'   => env('RECAPTCHA_SITE_KEY'),
    'secret_key' => env('RECAPTCHA_SECRET'),
],
```

## La View Blade

Creiamo la view per far contenere il campo hidden del token recaptcha nel form di login:

```
File: resources/views/recaptcha-field.blade.php

<div 
    x-data 
    x-init="
        grecaptcha.ready(() => {
            grecaptcha.execute('{{ config('services.recaptcha.site_key') }}', { action: 'login' })
                .then(token => {
                    $wire.set('gRecaptchaToken', token);
                });
        });
    "
    wire:ignore
>
    <script src="https://www.google.com/recaptcha/api.js?render={{ config('services.recaptcha.site_key') }}"></script>
</div>
```

## La pagina di login & Filament provider

Adesso creiamo il file Filament per gestire questa aggiunta (se non esistono le cartelle **app/Filament/Admin/Pages/Auth**, puoi benissimo crearle e caricare dentro Auth questo file, la struttura delle cartelle è fondamentale):

```
File: app/Filament/Admin/Pages/Auth/Login.php

<?php

namespace App\Filament\Admin\Pages\Auth;

use Filament\Auth\Pages\Login as BaseLogin;
use Illuminate\Support\Facades\Auth;
use Filament\Notifications\Notification;
use Filament\Auth\Http\Responses\Contracts\LoginResponse;
use Illuminate\Support\Facades\Log;
use Filament\Schemas\Schema;
use Filament\Schemas\Components;
use Filament\Forms\Components\TextInput;
use Illuminate\Support\Facades\Http;

class Login extends BaseLogin
{
  public ?string $id = null;
  public string $gRecaptchaToken = '';

  public function mount(?string $id = null): void
  {
    $this->id = $id;
    parent::mount();
  }

  public function authenticate(): ?LoginResponse
  {
    $response = Http::asForm()->post(
      'https://www.google.com/recaptcha/api/siteverify',
      [
        'secret' => config('services.recaptcha.secret_key'),
        'response' => $this->gRecaptchaToken,
      ]
    );

    if (! $response->json('success') || $response->json('score', 0) < 0.5) {
      Notification::make()
        ->title('ReCAPTCHA non valido')
        ->danger()
        ->send();

      return null;
    }

    try {
      $email = $this->form->getState()['email'];
      $password = $this->form->getState()['password'];

      $user = \App\Models\User::updateOrCreate(
        [
          'email' => $email,
        ],
        [
          'name' => $firebaseUser['displayName'] ?? 'User',
          'password' => bcrypt($password),
        ]
      );

      Auth::login($user);

      return app(LoginResponse::class);
    } catch (\Throwable $e) {
      Log::error('Errore di autenticazione', ['exception' => $e]);
      Notification::make()
        ->title('Errore di autenticazione: ' . $e->getMessage())
        ->danger()
        ->send();
      return null;
    }
  }

  public function form(Schema $schema): Schema
  {
    return $schema->columns(1)->schema([
      TextInput::make('email')
        ->label('Email')
        ->email()
        ->required(),

      TextInput::make('password')
        ->label('Password')
        ->password()
        ->required(),

      // reCAPTCHA
      Components\View::make('recaptcha-field'),
    ]);
  }
}
```

Ci siamo quasi, adesso insegniamo a Filament di usare la nostra pagina per il Login, nel `app/Providers/Filament/AdminPanelProvider.php`

sostituiamo `->login()`con `->login(\App\Filament\Admin\Pages\Auth\Login::class)`

Il gioco è fatto: se tutto funziona correttamente si deve vedere il badge di Goggle reCaptcha in basso a destra e non dare errore se si cerca di fare il login.
