josiasmontag / laravel-recaptchav3

Laravel package for Google's Recaptcha V3
MIT License
188 stars 37 forks source link

reCAPTCHA will timeout #21

Open EdwardKingAlexander opened 2 years ago

EdwardKingAlexander commented 2 years ago

If you are on the page for too long, when you submit the form, there will be a timeout and the reCAPTCHA will not validate. Perhaps, adding a built in function that only sets the token when the form is submitted would solve the issue?

fabiomlferreira commented 2 years ago

Exactly this current approach is not correct, the request for the token should be made only when the user click on the submit button.

fabiomlferreira commented 2 years ago

I think you can adde some parameters to field() function and create a javascript function that will be fired when the user hit submit and at that point do the request to recaptcha api and then submit the form, I edited your function without break compatibility

/**
* Create the field for recaptcha response, if the $requestOnSubmit is false the token is requested on the page
* load can cause error if the user take more than 2 minutes to submit the form because the token
* have a 2minutes timeout, the other option its a better approach
* @param $action
* @param $name
* @param $requestOnSubmit boolean if true the script will only call the api on form submit
* @param $formId the form id is required if the $requestOnSubmit is true
* @param $functionName for default the value is onClickRecaptcha and the onclick="onClickRecaptcha(event)" shoud be added on submit button
* @return string
*/
public function field($action, $name = 'g-recaptcha-response', $requestOnSubmit=false, $formId=null, $functionName="onClickRecaptcha")
{
    $fieldId = uniqid($name . '-', false);
    $html = '<input type="hidden" name="' . $name . '" id="' . $fieldId . '">';
    if ($requestOnSubmit == false){
        $html .= "<script>
          grecaptcha.ready(function() {
              grecaptcha.execute('" . $this->sitekey . "', {action: '" . $action . "'}).then(function(token) {
                 document.getElementById('" . $fieldId . "').value = token;
              });
          });
          </script>";
    }else{
        $html .= "<script>
        function " . $functionName . "(e) {
            e.preventDefault();
            grecaptcha.ready(function() {
              grecaptcha.execute('" . $this->sitekey . "', {action: '" . $action . "'}).then(function(token) {
                 document.getElementById('" . $fieldId . "').value = token;
                 document.getElementById('" . $formId . "').submit();
              });
            });
        }
    </script>";
    }
    return $html;
}

With this you can have a code like this

<form id="my-form" method="post" action="/register">
    {!! RecaptchaV3::field('register') !!}
    {!! RecaptchaV3::field('register', 'g-recaptcha-response', true, 'my-form') !!}
    <input type="submit" value="Register"  onclick="onClickRecaptcha(event)"></input>
</form>

This will work like it's supposed

stewartsims commented 1 year ago

Thanks - this updated field function seems to work for me. We were having intermittent issues with validation failing and I suspected a timeout issue. This seems like a good candidate for a PR to submit back into this project? I'm happy to put one together at some point if needed.

shabyis commented 9 months ago

Hey Guys Can you merge this into the package so we can use this?

stewartsims commented 9 months ago

Not sure this is maintained, but I've just I've submitted a PR with @fabiomlferreira 's changes: https://github.com/josiasmontag/laravel-recaptchav3/pull/37