Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reCaptcha v3 handle score callback

I followed recaptcha v3 example and managed to make it return a callback with a score for a page, similar with their demo.

What I don't understand is how to handle the score that is returned.

I understand that the success is based on the treshold. Using the github package the backend verification is returning json (fail or success) back to the frontend.Am I supposed to handle the fail or success in the front end using javascript? What if the browser has the javascript disabled?

I was thinking to use the recaptcha v3 on all the pages and block the users considered bots for an amount of time.

I am using laravel but I can't figure out how to handle the verification in the middleware, or somewhere else, in order to block the users if they don't have a token (javascript is disabled) or they are considered bots.

like image 583
Victordb Avatar asked Sep 14 '18 14:09

Victordb


1 Answers

reCAPTCHA token should be validated server side. First of all, attach generated token into your form:

grecaptcha.ready(function() {
    grecaptcha.execute('{{env('RECAPTCHA_V3_PUBLIC_KEY')}}', {action: 'contactform'}).then(function(token) {
        $('<input>').attr({
            type: 'hidden',
            name: 'g-recaptcha-response',
            value: token
        }).prependTo('.contact-form')
    });
});

Then when you capture the input on you controller, you can use a custom form request:

<?php

namespace App\Http\Requests;

use App\Rules\RecaptchaV3;
use Illuminate\Foundation\Http\FormRequest;

class ContactFormRequest extends FormRequest
{
    public function rules()
    {
        $rules = [
            'name' => 'required',
            'email' => 'required|email',
            'message' => 'required',
            'g-recaptcha-response' => ['required', new RecaptchaV3],
        ];

        return $rules;
    }
...

}

g-recaptcha-response field is required so if users disable JS they will get an error when form input is validated.

Next for g-recaptcha-response we apply a custom validation rule: RecaptchaV3.

Here's my implementation:

<?php

namespace App\Rules;

use GuzzleHttp\Client;
use Illuminate\Contracts\Validation\Rule;

class RecaptchaV3 implements Rule
{
    public function passes($attribute, $value)
    {
        $client = new Client();

        $response = $client->post('https://www.google.com/recaptcha/api/siteverify', [
            'form_params' => [
                'secret' => env('RECAPTCHA_V3_PRIVATE_KEY'),
                'response' => $value,
                'remoteip' => $_SERVER['REMOTE_ADDR'],
            ]
        ]);

        $decoded = json_decode($response->getBody());

        return $decoded->success;
    }

    public function message()
    {
        return "You didn't pass reCAPTCHA challenge!";
    }
}

Next, in your controller use the above form request:

public function processContactForm(ContactFormRequest $request)
{
    ...
}

Hope this helps.

like image 183
Marian Avatar answered Oct 06 '22 20:10

Marian