Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #43 from DarkGhostHunter/master
Browse files Browse the repository at this point in the history
Version 6.0
  • Loading branch information
DarkGhostHunter authored Oct 31, 2021
2 parents 7b4532d + f74a5d7 commit fb52c82
Show file tree
Hide file tree
Showing 32 changed files with 1,654 additions and 912 deletions.
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: daily
time: "09:00"
open-pull-requests-limit: 10
8 changes: 3 additions & 5 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [7.4, 8.0]
laravel: [7.*, 8.*]
php: [8.0, 8.1]
laravel: [8.*]
dependency-version: [prefer-lowest, prefer-stable]
include:
- laravel: 7.*
testbench: ^5.18
- laravel: 8.*
testbench: ^6.14
testbench: ^6.22

name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.dependency-version }}

Expand Down
115 changes: 69 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,18 @@

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.

## Table of Contents

* [Requirements](#requirements)
* [Installation](#installation)
* [Set Up](#set-up)
* [Usage](#usage)
* [Frontend integration](#frontend-integration)
* [Advanced configuration](#advanced-configuration)
* [Testing with Captchavel](#testing-with-captchavel)
* [Security](#security)
* [License](#license)
It uses your Laravel HTTP Client **async HTTP/2**, making your app **fast**. You only need a couple of lines to integrate.

## Requirements

* Laravel 7.x, 8.x, or later
* PHP 7.4, 8.0 or later
* Laravel 8.x, or later
* PHP 8.0 or later

> If you need support for old versions, consider sponsoring or donating.
## Installation

You can install the package via composer:
You can install the package via Composer:

```bash
composer require darkghosthunter/captchavel
Expand Down Expand Up @@ -65,37 +53,35 @@ Usage differs based on if you're using checkbox, invisible, or Android challenge

### Checkbox, invisible and Android challenges

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.
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 (you can change it later) 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.

```php
use App\Http\Controllers\Auth\LoginController;

Route::post('login', [LoginController::class, 'login'])->middleware('recaptcha:checkbox');
```
```

When the validation fails, the user will be redirected back, or a JSON response will be returned with the validation errors.

> You can change the input name from `g-recaptcha-response` to a custom using a second parameter, like `recaptcha.checkbox:my_input_name`.
### Score-driven challenge

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.
The reCAPTCHA v3 middleware works differently from v2. This is a score-driven response is _always_ a success, but the challenge scores between `0.0` and `1.0`. Human-like interaction will be higher, while robots will score lower. The default threshold is `0.5`, but this can be changed globally or per-route.

Simply add the `recaptcha.score` middleware to your route:
To start using it, simply add the `recaptcha.score` middleware to your route:

```php
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`:
Once the challenge has been received, you will have access to two methods from the Request class or instance: `isHuman()` and `isRobot()`, which return `true` or `false`:

```php
public function store(Request $request, Post $post)
Expand All @@ -115,6 +101,18 @@ public function store(Request $request, Post $post)
}
```

You can also have access to the response from reCAPTCHA using the `response()` method of the `Captchavel` facade:

```php
use DarkGhostHunter\Captchavel\Facades\Captchavel;

$response = Captchavel::response();

if ($response->score > 0.2) {
return 'Try again!';
}
```

#### Threshold, action and input name

The middleware accepts three additional parameters in the following order:
Expand All @@ -130,7 +128,28 @@ 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 .
> When checking the action name, ensure your frontend action matches with the expected in the middleware.
#### Bypassing on authenticated users

Sometimes you may want to bypass reCAPTCHA checks on authenticated user, or automatically receive it as a "human" on score-driven challenges. While in your frontend you can programmatically disable reCAPTCHA when the user is authenticated, on the backend you can specify the guards to check as the last middleware parameters.

Since having a lot of arguments on a middleware can quickly become spaghetti code, use the `ReCaptcha` helper to declare it using fluid methods.

```php
use App\Http\Controllers\CommentController;
use App\Http\Controllers\MessageController;
use DarkGhostHunter\Captchavel\ReCaptcha;
use Illuminate\Support\Facades\Route

Route::post('message/send', [MessageController::class, 'send'])
->middleware(ReCaptcha::invisible()->except('user')->toString());

Route::post('comment/store', [CommentController::class, 'store'])
->middleware(ReCaptcha::score(0.7)->action('comment.store')->except('admin', 'moderator')->toString());
```

> Ensure you set the middleware as `->toString()` when using the helper to declare the middleware.
#### Faking reCAPTCHA scores

Expand All @@ -142,12 +161,14 @@ 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.
From there, you can fake a robot response by filling the `is_robot` input in your form.

```blade
<form id="comment" method="post">
<textarea name="body"></textarea>
<input type="checkbox" name="is_robot" checked>
@env('local', 'testing')
<input type="checkbox" name="is_robot" checked>
@endenv
<button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'>Login</button>
</form>
```
Expand All @@ -172,7 +193,7 @@ You can use the `captchavel()` helper to output the site key depending on the ch
## Advanced configuration

Captchavel is intended to work out-of-the-box, but you can publish the configuration file for fine-tuning and additional reCAPTCHA verification.
Captchavel is intended to work out-of-the-box, but you can publish the configuration file for fine-tuning the reCAPTCHA verification.

```bash
php artisan vendor:publish --provider="DarkGhostHunter\Captchavel\CaptchavelServiceProvider" --tag="config"
Expand All @@ -183,13 +204,15 @@ You will get a config file with this array:
```php
<?php

use DarkGhostHunter\Captchavel\Captchavel;

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' => [
'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' => [
// ...
]
];
Expand All @@ -205,15 +228,17 @@ return [
];
```

By default, Captchavel is disabled, so it doesn't check reCAPTCHA challenges. You can forcefully enable it with the `CAPTCHAVEL_ENABLE` environment variable.
By default, Captchavel is disabled, so it doesn't check reCAPTCHA challenges, and on score-driven routes, it will always resolve as human interaction.

You can forcefully enable it with the `CAPTCHAVEL_ENABLE` environment variable.

```dotenv
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`.
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.
> When switched off, the reCAPTCHA v2 challenges are not validated in the Request input, so you can safely disregard any frontend script or reCAPTCHA tokens or boxes.
### Fake responses

Expand All @@ -223,7 +248,7 @@ CAPTCHAVEL_FAKE=true

If Captchavel is [enabled](#enable-switch), setting this to true will allow your application to [fake v3-score responses from reCAPTCHA servers](#faking-recaptcha-scores).

> This is automatically set to `true` when [running unit tests](#testing-with-captchavel).
> This is automatically set to `true` when [running unit tests](#testing-score-with-captchavel).
### Hostname and APK Package Name

Expand All @@ -232,7 +257,7 @@ 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](https://www.google.com/recaptcha/admin/), you will have to issue the strings in the environment file.
If you are not verifying the Hostname or APK Package Name in your [reCAPTCHA Admin Panel](https://www.google.com/recaptcha/admin/), you will have to issue them 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.

Expand All @@ -244,7 +269,7 @@ return [
];
```

Default threshold to check against reCAPTCHA v3 challenges. Values **equal or above** will be considered as human.
Default threshold to check against reCAPTCHA v3 challenges. Values **equal or above** will be considered "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](#threshold-action-and-input-name).

Expand All @@ -264,15 +289,14 @@ Here is the full array of [reCAPTCHA credentials](#set-up) to use depending on t

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](#fake-responses).
On the other hand, reCAPTCHA v3 (score) responses [are always faked](#fake-responses) as humans, even if [Captchavel is disabled](#enable-switch). This guarantees you can always access the response in your controller.

To do that, you should [enable Captchavel](#enable-switch) on your tests, through the `.env.testing` environment file, or in [PHPUnit environment section](https://phpunit.readthedocs.io/en/9.5/configuration.html?highlight=environment#the-env-element). If you use another testing framework, refer to its documentation.
To modify the score in your tests, you should [enable faking](#fake-responses) on your tests through the `.env.testing` environment file, or in [PHPUnit environment section](https://phpunit.readthedocs.io/en/9.5/configuration.html?highlight=environment#the-env-element). If you use another testing framework, refer to its documentation.

```xml
<phpunit>
<!-- ... -->
<php>
<env name="CAPTCHAVEL_ENABLE" value="true"/>
<env name="CAPTCHAVEL_FAKE" value="true"/>
</php>
</phpunit>
Expand All @@ -283,7 +307,6 @@ Alternatively, you can change the configuration before your unit test:
```php
public function test_this_route()
{
config()->set('captchavel.enable', true);
config()->set('captchavel.fake', true);

// ...
Expand Down Expand Up @@ -316,7 +339,7 @@ $this->post('login', [
])->assertViewIs('login.2fa');
```

> Fake responses don't come with actions, hostnames or APK package names.
> Fake responses don't come with actions, hostnames or APK package names, so these are not validated.
### Faking Scores manually

Expand Down
18 changes: 9 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
}
],
"require": {
"php": ">=7.4",
"php": "^8.0",
"ext-json": "*",
"illuminate/support": "^7.0||^8.0",
"illuminate/http": "^7.0||^8.0",
"illuminate/routing": "^7.0||^8.0",
"illuminate/container": "^7.0||^8.0",
"illuminate/events": "^7.0||^8.0",
"guzzlehttp/guzzle": "^6.0||^7.0"
"illuminate/support": "^8.0",
"illuminate/http": "^8.0",
"illuminate/routing": "^8.0",
"illuminate/container": "^8.0",
"illuminate/events": "^8.0",
"guzzlehttp/guzzle": "^7.4.0"
},
"require-dev": {
"orchestra/testbench": "^5.18||^6.14.0",
"phpunit/phpunit": "^9.5.2"
"orchestra/testbench": "^6.22.0",
"phpunit/phpunit": "^9.5.10"
},
"autoload": {
"psr-4": {
Expand Down
16 changes: 9 additions & 7 deletions config/captchavel.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
| Main switch
|--------------------------------------------------------------------------
|
| This switch enables the main Captchavel middleware that will detect all
| This switch enables the main Captchavel v2 middleware to detect all the
| challenges incoming. You should activate it on production environments
| and deactivate it on local environments unless you to test responses.
|
Expand All @@ -26,6 +26,8 @@
| servers in local development. To do this, simply enable the environment
| variable and then issue as a checkbox parameter is_robot to any form.
|
| For v2 middleware, faking means bypassing checks.
|
*/

'fake' => env('CAPTCHAVEL_FAKE', false),
Expand All @@ -49,17 +51,17 @@
| Threshold
|--------------------------------------------------------------------------
|
| For reCAPTCHA v3, which is an score-driven interaction, this default
| For reCAPTCHA v3, which is a score-driven interaction, this default
| threshold is the slicing point between bots and humans. If a score
| is below this threshold, it means the request was made by a bot.
| is below this threshold it means the request was made by a bot.
|
*/

'threshold' => 0.5,

/*
|--------------------------------------------------------------------------
| Credenctials
| Credentials
|--------------------------------------------------------------------------
|
| The following is the array of credentials for each version and variant
Expand All @@ -70,9 +72,9 @@

'credentials' => [
Captchavel::CHECKBOX => [
'secret' => env('RECAPTCHA_CHECKBOX_SECRET', Captchavel::TEST_V2_SECRET),
'key' => env('RECAPTCHA_CHECKBOX_KEY', Captchavel::TEST_V2_KEY),
],
'secret' => env('RECAPTCHA_CHECKBOX_SECRET', Captchavel::TEST_V2_SECRET),
'key' => env('RECAPTCHA_CHECKBOX_KEY', Captchavel::TEST_V2_KEY),
],
Captchavel::INVISIBLE => [
'secret' => env('RECAPTCHA_INVISIBLE_SECRET', Captchavel::TEST_V2_SECRET),
'key' => env('RECAPTCHA_INVISIBLE_KEY', Captchavel::TEST_V2_KEY),
Expand Down
7 changes: 7 additions & 0 deletions resources/lang/en/validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

return [
'match' => 'The reCAPTCHA challenge does not matches this action.',
'missing' => 'The reCAPTCHA challenge was not completed or is missing.',
'error' => 'Error resolving the reCAPTCHA challenge: :errors.',
];
Loading

0 comments on commit fb52c82

Please sign in to comment.