Integrate reCAPTCHA into your Laravel app better than the Big G itself!
It uses your Laravel HTTP Client and HTTP/2, making your app fast. You only need a couple of lines to integrate.
- Requirements
- Installation
- Set Up
- Usage
- Frontend integration
- Advanced configuration
- Testing with Captchavel
- Security
- License
- Laravel 7.x, 8.x, or later
- PHP 7.4, 8.0 or later
If you need support for old versions, consider sponsoring or donating.
You can install the package via composer:
composer require darkghosthunter/captchavel
Add the reCAPTCHA keys for your site to the environment file of your project. You can add each of them for reCAPTCHA v2 checkbox, invisible, Android, and score.
If you don't have one, generate it in your reCAPTCHA Admin panel.
RECAPTCHA_CHECKBOX_SECRET=6t5geA1UAAAAAN...
RECAPTCHA_CHECKBOX_KEY=6t5geA1UAAAAAN...
RECAPTCHA_INVISIBLE_SECRET=6t5geA2UAAAAAN...
RECAPTCHA_INVISIBLE_KEY=6t5geA2UAAAAAN...
RECAPTCHA_ANDROID_SECRET=6t5geA3UAAAAAN...
RECAPTCHA_ANDROID_KEY=6t5geA3UAAAAAN...
RECAPTCHA_SCORE_SECRET=6t5geA4UAAAAAN...
RECAPTCHA_SCORE_KEY=6t5geA4UAAAAAN...
This allows you to check different reCAPTCHA mechanisms using the same application, in different environments.
Captchavel already comes with v2 keys for local development. For v3, you will need to create your own set of credentials.
Usage differs based on if you're using checkbox, invisible, or Android challenges, or the v3 score-driven challenge.
After you integrate reCAPTCHA into your frontend or Android app, set the Captchavel middleware in the POST
routes where a form with reCAPTCHA is submitted. The middleware will catch the g-recaptcha-response
input and check if it's valid.
recaptcha:checkbox
for explicitly rendered checkbox challenges.recaptcha:invisible
for invisible challenges.recaptcha:android
for Android app challenges.
When the validation fails, the user will be redirected back to the form route, or a JSON response will be returned with the validation errors.
use App\Http\Controllers\Auth\LoginController;
Route::post('login', [LoginController::class, 'login'])->middleware('recaptcha:checkbox');
You can change the input name from
g-recaptcha-response
to a custom using a second parameter, likerecaptcha.checkbox:my_input_name
.
The reCAPTCHA v3 middleware works differently from v2. This is a score-driven response is always a success, but the challenge is scored between 0.0
and 1.0
. Robots will get lower scores, while human-like interaction will be higher.
The default threshold is 0.5
, which will set apart robots that score less than that.
Simply add the recaptcha.score
middleware to your route:
use App\Http\Controllers\CommentController;
Route::post('comment', [CommentController::class, 'create'])->middleware('recaptcha.score');
Once the challenge has been received, you will have access to two methods from the Request instance: isHuman()
and isRobot()
, which return true
or false
:
public function store(Request $request, Post $post)
{
$request->validate([
'body' => 'required|string|max:255'
]);
$comment = $post->comment()->make($request->only('body'));
// Flag the comment as "moderated" if it was a written by robot.
$comment->moderated = $request->isRobot();
$comment->save();
return view('post.comment.show', ['comment' => $comment]);
}
The middleware accepts three additional parameters in the following order:
- Threshold: Values above or equal are considered human.
- Action: The action name to optionally check against.
- Input: The name of the reCAPTCHA input to verify.
use App\Http\Controllers\CommentController;
Route::post('comment', [CommentController::class, 'create'])
->middleware('recaptcha.score:0.7,login,custom-recaptcha-input');
When checking the action name, ensure your Frontend action matches .
You can easily fake a reCAPTCHA response scores in your local development by setting CAPTCHAVEL_FAKE
to true
.
CAPTCHAVEL_FAKE=true
This environment variable changes the reCAPTCHA Factory for a fake one, which will fake successful responses from reCAPTCHA, instead of resolving real challenges.
From there, you can fake a robot or human response by adding an is_robot
and returning true
or false
, respectively.
<form id="comment" method="post">
<textarea name="body"></textarea>
<input type="checkbox" name="is_robot" checked>
<button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'>Login</button>
</form>
Check the official reCAPTCHA documentation to integrate the reCAPTCHA script in your frontend, or inside your Android application.
You can use the captchavel()
helper to output the site key depending on the challenge version you want to render: checkbox
, invisible
, android
or score
(v3).
<form id='login' method="POST">
<input type="email" name="email">
<input type="password" name="password">
<button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'>Login</button>
<br/>
</form>
You can also retrieve the key using
android
for Android apps.
Captchavel is intended to work out-of-the-box, but you can publish the configuration file for fine-tuning and additional reCAPTCHA verification.
php artisan vendor:publish --provider="DarkGhostHunter\Captchavel\CaptchavelServiceProvider" --tag="config"
You will get a config file with this array:
<?php
return [
'enable' => env('CAPTCHAVEL_ENABLE', false),
'fake' => env('CAPTCHAVEL_FAKE', false),
'hostname' => env('RECAPTCHA_HOSTNAME'),
'apk_package_name' => env('RECAPTCHA_APK_PACKAGE_NAME'),
'threshold' => 0.5,
'credentials' => [
// ...
]
];
<?php
return [
'enable' => env('CAPTCHAVEL_ENABLE', false),
];
By default, Captchavel is disabled, so it doesn't check reCAPTCHA challenges. You can forcefully enable it with the CAPTCHAVEL_ENABLE
environment variable.
CAPTCHAVEL_ENABLE=true
This can be handy to enable on some local or development environments to check real interaction using the included localhost test keys, which only work on localhost
.
When switched off, the reCAPTCHA challenge is not validated in the Request input, so you can safely disregard any frontend script or reCAPTCHA tokens or boxes.
CAPTCHAVEL_FAKE=true
If Captchavel is enabled, setting this to true will allow your application to fake v3-score responses from reCAPTCHA servers.
This is automatically set to
true
when running unit tests.
RECAPTCHA_HOSTNAME=myapp.com
RECAPTCHA_APK_PACKAGE_NAME=my.package.name
If you are not verifying the Hostname or APK Package Name in your reCAPTCHA Admin Panel, you will have to issue the strings in the environment file.
When the reCAPTCHA response from the servers is retrieved, it will be checked against these values when present. In case of mismatch, a validation exception will be thrown.
return [
'threshold' => 0.4
];
Default threshold to check against reCAPTCHA v3 challenges. Values equal or above will be considered as human.
If you're not using reCAPTCHA v3, or you're fine with the default, leave this alone. You can still override the default in a per-route basis.
return [
'credentials' => [
// ...
]
];
Here is the full array of reCAPTCHA credentials to use depending on the version. Do not change the array unless you know what you're doing.
On testing, when Captchavel is disabled, routes set with the v2 middleware won't need to input the challenge in their body as it will be not verified.
On the other hand, reCAPTCHA v3 (score) responses can be automatically faked.
To do that, you should enable Captchavel on your tests, through the .env.testing
environment file, or in PHPUnit environment section. If you use another testing framework, refer to its documentation.
<phpunit>
<!-- ... -->
<php>
<env name="CAPTCHAVEL_ENABLE" value="true"/>
<env name="CAPTCHAVEL_FAKE" value="true"/>
</php>
</phpunit>
Alternatively, you can change the configuration before your unit test:
public function test_this_route()
{
config()->set('captchavel.enable', true);
config()->set('captchavel.fake', true);
// ...
}
When faking challenges, there is no need to add any reCAPTCHA token or secrets in your tests.
When using reCAPTCHA v3 (score), you can fake a response made by a human or robot by simply using the fakeHuman()
and fakeRobot()
methods, which will score 1.0
or 0.0
respectively for all subsequent requests.
<?php
use DarkGhostHunter\Captchavel\Facades\Captchavel;
// Let the user login normally.
Captchavel::fakeHuman();
$this->post('login', [
'email' => '[email protected]',
'password' => '123456',
])->assertRedirect('user.welcome');
// ... but if it's a robot, force him to use 2FA.
Captchavel::fakeRobot();
$this->post('login', [
'email' => '[email protected]',
'password' => '123456',
])->assertViewIs('login.2fa');
Fake responses don't come with actions, hostnames or APK package names.
Alternatively, fakeScore()
method will fake responses with any score you set.
<?php
use DarkGhostHunter\Captchavel\Facades\Captchavel;
// A human comment should be public.
Captchavel::fakeScore(0.7);
$this->post('comment', [
'body' => 'This comment was made by a human',
])->assertSee('Your comment has been posted!');
// A robot should have its comment moderated.
Captchavel::fakeScore(0.4);
$this->post('comment', [
'body' => 'Comment made by robot.',
])->assertSee('Your comment will be reviewed before publishing.');
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.