Integrating Google reCAPTCHA with Laravel, Inertia JS and Vue 3.
Tags: laravel, vue, tutorial
Published: 2022-01-17 17:04:12

I will show you how to add the Google reCAPTCHA version 3 with Laravel with a few simple steps.

I assume you already installed Laravel with Jetstream, InertiaJS and Vue3. If not, [this](https://jetstream.laravel.com/) link will help you to install.

### Setup 1: 

Register your site in the [Google reCAPTCHA](https://www.google.com/recaptcha/admin/create) and get the reCAPTCHA site key and Secret Key.

Configure those values in the config services.php file for better accessibility and management.


```php

 'google_recaptcha' => [
   'url' => 'https://www.google.com/recaptcha/api/siteverify',
   'site_key' => env('GOOGLE_RECAPTCHA_SITE_KEY'),
   'secret_key' => env('GOOGLE_RECAPTCHA_SECRET_SITE_KEY'),
 ]

```

To access the reCAPTCHA site key in the frontend, share through the HandleInertiaRequest file. Directly mentioning the site key in the front end isn't a great idea.


```php
 public function share(Request $request)
 {
     return array_merge(parent::share($request), [
      'recaptcha_site_key' => config('services.google_recaptcha.site_key'),
     ]);
 }

```


### Setup 2:

Install [Vue recaptcha v3](https://www.npmjs.com/package/vue-recaptcha-v3) and import in app.js file.

```js
import { VueReCaptcha, useReCaptcha } from 'vue-recaptcha-v3'
...


createInertiaApp({
  title: (title) => `${title} - ${appName}`,
  resolve: (name) => require(`./Pages/${name}.vue`),
  setup({ el, app, props, plugin }) {
    const captcheKey = props.initialPage.props.recaptcha_site_key;
    return createApp({ render: () => h(app, props) })
      .use(plugin)
      .use(VueReCaptcha, { siteKey: captcheKey } )
      .mixin({ methods: { route } })
      .mount(el)
  },
})

```

### Step 3:

To add Google reCAPTCHA to the form. Here, I used a sample form to demonstrate the Google reCAPTCHA with Vue 3 composition API.

```vue
<form action="#" method="POST"  @submit.prevent="recaptcha">
   ...

   <jet-input-error :message="form.errors.captcha_token" class="mt-2" />
</form>

<script>
import { useForm } from '@inertiajs/inertia-vue3'
import { useReCaptcha } from "vue-recaptcha-v3";


export default {

  setup() {
   
    const form = useForm({
      name: null,
      email: null,
      phone: null,
      message: null,
      captcha_token :null,
    })

    const { executeRecaptcha, recaptchaLoaded } = useReCaptcha()
    const recaptcha = async () => {
      await recaptchaLoaded()
      form.captcha_token = await executeRecaptcha('login')
      submit();
    }
    
    function submit() {
      form.post(route('contact-us.store'), {
        preserveScroll: true,
        onSuccess: () => console.log('success'),
      })
    }

    return {
      form, submit ,recaptcha,
    }
  },
}


</script>

```

### Step 4
Create a Laravel custom rule to verify the token and score. Here, I rejected the form if the score <= 0.5 and status was not equals to true.

```php
<?php

namespace App\Rules;

use Illuminate\Support\Facades\Http;
use Illuminate\Contracts\Validation\Rule;

class Recaptcha implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $endpoint = config('services.google_recaptcha');

        $response = Http::asForm()->post($endpoint['url'], [
            'secret' => $endpoint['secret_key'],
            'response' => $value,
        ])->json();

        if(  $response['success'] && $response['score'] > 0.5) {
            return true;
        }
     
        return false;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'Something goes wrong. Please contact us directly through the phone or email.';
    }
}

```

Finally, add in the controller to validate the input request along with reCAPTCHA token.

use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Redirect;
use App\Rules\Recaptcha;

...

```php
public function store() {
 $contact = Contact::create(
   Request::validate([
     'name' => ['required', 'max:50'],
     'email' => ['required', 'max:100','email'],
     'phone' => ['nullable', 'max:13'],
     'message' => ['required', 'max:2000'],
     'captcha_token'  => [new Recaptcha],
    ])
  );  

 return Redirect::route('contact-us');   
        
}


```

I hope, this tutorial helps you to integrate Google reCAPTCHA 3 with Laravel. Please let me know if it doesn't work for you.

Thank you.