phpinvisible-recaptcharecaptcha-v3

How to solve Google v3 reCaptcha timeout?


We have a PHP form that is several tabs and times-out on the reCaptcha. Everything is done in one page and it works perfectly fine IF the form is completed in <3 minutes.

The idea of a solution is to move the form processing and reCaptcha to a secondary page for processing.

The problem is that the form page polls the google service for reCaptcha and collects a token value to a hidden field.

<input type="hidden" name="recaptcha_response" id="recaptchaResponse">

The problem is how to request this token on the server side processing page? Here is the code used on the client side form page. I need to somehow regenerate the token value to apply as :

$recaptcha_response

Here is the working version on the form page. It's easy to remove the requirement on Posting the token from the form page, just not sure how to regenerate the token to use on the server side page.

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['recaptcha_response'])) {

// Build POST request:
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_secret = RECAPTCHA_SECRET_KEY;
$recaptcha_response = $_POST['recaptcha_response'];
$remoteip = $_SERVER['REMOTE_ADDR'];

// Make and decode POST request:
$recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response. '&remoteip='.$remoteip);
$recaptcha = json_decode($recaptcha);

// Take action based on the score returned:
if ($recaptcha->score >= 0.5) {

EDIT TO ADD: Would making the initialization of the reCaptcha until Submit delay the timing issue since this seems to be an option:

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

"2. Call grecaptcha.execute on an action or when the page loads"


Solution

  • We've been running into this recently, too. I found this solution on GitHub and it's been working well for us.

    This has the benefit of only asking for a token when the user interacts with the page (such as submitting a form) instead of having to keep asking for one.

    <script>
      grecaptcha.ready(function() {
          document.getElementById('contactform').addEventListener("submit", function(event) {
    
            event.preventDefault();
    
            grecaptcha.execute('mykey', {action: 'homepage'}).then(function(token) {
               document.getElementById("googletoken").value = token; 
               document.getElementById('contactform').submit();
            });        
          }, false);
    
      });
    </script>