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 link will help you to install.
Setup 1:
Register your site in the Google reCAPTCHA and get the reCAPTCHA site key and Secret Key.
Configure those values in the config services.php file for better accessibility and management.
'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.
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 and import in app.js file.
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.
<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
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;
...
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.
Top comments (2)
Hi, first thank for excellent tutorial, one question can you help me?, how can show the Badge only at a component, i load the plugin with Bagde hide, but i need show it in a component, i are not how call the intance of recaptcha in my component, show my code, resource/..app.js
return createApp({render: () => h(app, props)})
.use(plugin)
.use(store)
.use(VueReCaptcha, {
siteKey: captcheKey,
loaderOptions: {
autoHideBadge: true
}
})
My component where a want show the badge:
onMounted(() => {
setTimeout(() => {
const recaptcha = this.$recaptcha
recaptcha.showBadge()
}, 5000)
})
The result, Uncaught TypeError: Cannot read properties of undefined (reading '$recaptcha')
How could it load only on the page/contact component instead of globally from app.js?