Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Nite's avatar
Level 1

Laravel Form Errors not showing when using Google RecaptchaV3

I implemented Google RecaptchaV3 for a user registration form (the code for this form was created with make:auth in a previous Laravel version (I think it was around 5.6)).

The user registration (and the captcha) work fine if the supplied form values pass the validation process, otherwise, the page just reloads (as it should), but with the $errors variable empty.

If I remove the Recaptcha JS code from the page, submitting the form with invalid data correctly refreshes the page and the $errors variable has the error messages for each invalid field.

Client:

//Just for testing..
{{ print_r($errors) }}
...
<form method="POST" id="dm-register-form" action="{{ route('register') }}">
...
  <input type="hidden" id="captcha-token" name="g-recaptcha-response" value="">
  <button type="button" id="btn-submit-registration">Submit</button>
...
<script>
	document.getElementById('btn-submit-registration').addEventListener('click', (e) => {
		e.preventDefault();
		grecaptcha.ready(function() {
			grecaptcha.execute('{{ config('app.captcha_site_key') }}', {action: 'register'}).then(function(token) {
				document.getElementById('captcha-token').value = token;
				document.getElementById('dm-register-form').submit();
			});
		});
	});
</script>

Server:

/**
 * Get a validator for an incoming registration request.
 *
 * @param  array  $data
 * @return \Illuminate\Contracts\Validation\Validator
 */
 protected function validator($request) {
	 return Validator::make($request->all(), [
		'name' => ['required', 'string', 'max:255'],
		'surname' => ['required', 'string', 'max:255'],
		'email' => ['required', 'string', 'email', 'max:255',],
		'password' => ['required', 'string', 'min:8', 'confirmed'],
		'g-recaptcha-response' => ['required', new CaptchaV3($request->ip(), 'register')],
	]
}
public function register(Request $request) {
	$this->validator($request)->validate();
	event(new Registered($user = $this->create($request->all())));
	...
}
<?php
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use ReCaptcha\ReCaptcha;

class CaptchaV3 implements Rule {
	private $remote_ip;
	private $actionName;

	/**
	 * Create a new rule instance.
	 *
	 * @return void
	 */
	public function __construct($remote_ip, $actionName) {
		$this->remote_ip = $remote_ip;
		$this->actionName = $actionName;
	}

	/**
	 * Determine if the validation rule passes.
	 *
	 * @param  string  $attribute
	 * @param  mixed  $value
	 * @return bool
	 */
	public function passes($attribute, $value) {
		$recaptcha = new ReCaptcha(config('app.captcha_secret_key'));
		$resp = $recaptcha->setExpectedAction($this->actionName)
			->setScoreThreshold(0.5)
			->verify($value, $this->remote_ip);

		return $resp->isSuccess();
	}

	/**
	 * Get the validation error message.
	 *
	 * @return string
	 */
	public function message() {
		return 'Captcha Failed.';
	}
}

Recaptcha V3 docs : https://developers.google.com/recaptcha/docs/v3

PHP Google package : https://github.com/google/recaptcha/

EDIT: After further testing, I found out that the problem only happens in the local environment (using xampp and http), while on the live server which uses https, it works.

On the local enviroment I get this warning in console when the page refreshes (after a submit with invalid data) :

Set-Cookie header is ignored in response from url: http://xampp.app.dm/en/register. Cookie length should be less than or equal to 4096 characters.

Another difference from the live server, is that in local I use those env settings :

CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=cookie

while in the live, I use memcached :

CACHE_DRIVER=memcached
QUEUE_CONNECTION=redis
SESSION_DRIVER=memcached
0 likes
0 replies

Please or to participate in this conversation.