2

I'm using HAML, Semantic UI and jQuery to generate my static site, and have a set of forms on a page which use reCAPTCHA v2. My web implementer ran out of time on the project so I've picked up the slack, but only know a little Javascript/Semantic/jQuery.

_header partial yields: <script src="https://www.google.com/recaptcha/api.js"></script>

my layout yields the form data:

<form action='https://liveformhq.com/form/<form uuid>' class='ui large form' id='formGeneral' method='POST'>
<snip>
<label>Message *</label>
<textarea name='message' placeholder='Say hello'></textarea>
</div>
<div class='field'>
<div class='g-recaptcha' data-callback='reCaptcha_general' data-sitekey='<my site key>'></div>
<input class='hiddenRecaptcha' id='gen_hiddenRecaptcha' name='gen_hiddenRecaptcha' type='hidden'>
<button class='ui primary large button' type='submit'>Send</button>
<a class='item' href='#top' rel='scrolltoanchor'>&#x2B06;</a>
</div>
<div class='ui error message'></div>
</form>

_footer partial yields the jQuery which I comment on as we step through:

I don't know why he used $('form').form({ instead of $('form').validate({ - Is this more recent jQuery? It picks up the 'empty' reCAPTCHA box though.

  // form validation
  //
  $('form').form({
      on: 'blur',
      fields: {
<snip>
          message: {
              identifier: 'message',
              rules: [{
                  type: 'empty',
                  prompt: 'Please enter your message'
              }]
          },
        gen_hiddenRecaptcha: {
            identifier: 'gen_hiddenRecaptcha',
            rules: [{
                gen_hiddenRecaptcha: { required: true },
                type: 'empty',
                prompt: 'Please check the reCAPTCHA check box'
            }]
        },
      }
  });

This appears to be getting the response (I can alert and see the response come out) and this correctly affects the semantic warning which goes away when the field is no longer empty.

  var reCaptcha_general = function(response) {
      $("#gen_hiddenRecaptcha").val(response);
  };

And so below I think is the problem. With all fields completed, the submit button doesn't work. I may have confused two different approaches before and tried to solve the problem with both at the same time.

When the submit is clicked, this function is called, but nothing happens.

  $('#formGeneral').submit(function(event) {
      if (!grecaptcha.getResponse()) {
          event.preventDefault(); //prevent form submit
          grecaptcha.execute();
      }
  });

UPDATE: I have just this edited in place as I have not had any answers yet.


UPDATE2: In order not to skew the comments below (and bearing in mind at this time of writing no answers to the below questions are submitted), I updated the code and wanted to share this in case someone else gets tangled up in the same way.

Revising the google docs after seeing other questions warning of ensuring you validate the response token separately, the form element id is renamed to be clearer that it carries the response token payload:

<div class="g-recaptcha" data-callback="reCaptcha_general" data-sitekey="<site-key>">
<input class="hiddenRecaptcha" id="gen_recaptchaResponseToken" name="gen_recaptchaResponseToken" type="hidden">

and in the footer, and this javascript to output warnings if the message box or reCAPTCHA are empty:

$('form').form({
    on: 'blur',
    fields: {
        message: {
            identifier: 'message',
            rules: [{
                type: 'empty',
                prompt: 'Please enter your message'
            }]
        },
        gen_recaptchaResponseToken: {
            identifier: 'gen_recaptchaResponseToken',
            rules: [{
                gen_recaptchaResponseToken: { required: true },
                type: 'empty',
                prompt: 'Please check the reCAPTCHA check box'
            }]
        },
    }
});

I thus updated the call back function with the new HTML form element ID:

var reCaptcha_general = function(response) {
    $("#gen_recaptchaResponseToken").val(response);
};

and finally removed the grecaptcha.getResponse() call completely as per suggestion:

$('#formGeneral').submit(function(event) {
}); 

and the form functions correctly. I think the reason why it does is because my form validation service (the very excellent liveform) have the secret I got when I signed up to the reCAPTCHA service with google. I've not heard back from them as yet confirming what they technically do on the backend, but as the form action POSTs to a liveformhq.com URL, at the least, I expect them to be hitting Google's siteverify API to confirm the reCAPTCHA response token is valid.

Questions:

  1. Am I right in thinking that with the above, I'm using jQuery form validation to prevent the form from being submitted by parsing the empty-ness of the response from the reCAPTCHA, rather than relying on grecaptcha.getResponse()?

  2. If so, do I even need the grecaptcha.getResponse() call?

  3. Although, am I right thinking that it is more secure to rely on grecaptcha.getResponse() and just make the jQuery form processing for that form element required: true just to get the warning prompt for the user?

volvox
  • 3,014
  • 16
  • 51
  • 80
  • Have you checked your server-side code for how its handling the collection of the recaptcha data? Is the value being posted to your form handler? What is the form handler's response from google when it attempts to validate the recaptcha code? – Lawrence Johnson Dec 07 '18 at 08:38
  • I’m using liveforms as a back end so I cannot ‘see’ in to what’s happening on the server side. Only what comes back. But I don’t know how to capture what comes back. I’ll google it. – volvox Dec 07 '18 at 12:49
  • I've amended the question to clarify. – volvox Dec 07 '18 at 13:58
  • Have you tried removing the `if (!grecaptcha.getResponse()) {` block to see if the submit works after checking the recaptcha box? IMO, that condition should be checking the `val()` of `#gen_hiddenRecaptcha` instead of querying the recaptcha object. – Lawrence Johnson Dec 07 '18 at 18:56
  • The `grecaptcha.getResponse()` should work, here is another method which may answer your question because it make the recaptcha field required. https://stackoverflow.com/questions/29612879/google-recaptcha-how-to-make-required/29613089#29613089 – colecmc Dec 07 '18 at 19:28
  • @LawrenceJohnson, when I remove the `if (!grecaptcha.getResponse()) { ` the form functions the same; i.e. I've managed to get it to work but it just doesn't feel right. I will update2 my question. – volvox Dec 07 '18 at 20:52
  • 1
    @colecmc thanks - judging from https://developers.google.com/recaptcha/docs/verify I can get the response 'one of three ways' i.e. if I'm getting the response token from the callback, the other two ways are redundant. Assuming my form service checks the siteverify API for me, I reckon I'm good to go. – volvox Dec 07 '18 at 22:20
  • Right, you got it. Hope it works out – colecmc Dec 10 '18 at 16:01
  • Ok for anyone getting to this point, that was the way forward that worked. If moderators want me to fortunate an answer, let me know but I think reading the docs as thoroughly as I subsequently had to to get to the answer will also. – volvox Dec 22 '18 at 15:25

0 Answers0