0

I'm trying to add reCaptcha to my resigration form on my website. I've followed a video tutorial on how to do it, however I'm struggling to adapt it to work with my form that use ajax to call a PHP file and does not actually submit the form. I've tried a few things suggested in previous questions, but none seem to get the intended result and instead display "I don't like robots" to the registration page. Some hints / suggestions would be nice if you can think of any.

<div class="g-recaptcha" data-sitekey="6LcXMg0UAAAAABmlDlOGa6onxqqzERZ483XOJbFm"></div>

Javascript

function Register(){
        var Forename = $("#txtForename" ).val();
        var Surname = $("#txtSurname" ).val();
        var Password = $("#txtPassword").val();
        var PasswordR = $("#txtPasswordR").val();
        var response = $("#g-recaptcha").val();
            $.post('functions/php/fncregister.php', {Forename: Forename, Surname: Surname, Password: Password, PasswordR: PasswordR, response: response}, function(data) {
                var returnValue = JSON.parse(data);
                if (returnValue['data'] == 0){
                    $('#mdlInfo').html('<p>Your account has been created under the username: <strong><span id="spnUsername">'+returnValue['username']+'</span></strong>. You <strong>must</strong> remember this as you will require it to log into your account.</p><p>Your account has also been added to a moderation que. <strong>You must wait until a member of staff activates your account!</strong></p>');
                    $("#mdlRegister").modal("show");
                }
                else if (returnValue['data'] == 1){
                    $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">Passwords did not match!</p>');
                }
                else if (returnValue['data'] == 3){
                    $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">An error occured when adding your details to the Database!</p>');
                }
                else if (returnValue['data'] == 4){
                    $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">I don\'t like Robots!</p>');
                }
            });
    }

PHP

<?php
//Retrieves variables from Javascript.
$Forename = $_POST["Forename"];
$Surname = $_POST["Surname"];
$Password = $_POST["Password"];
$PasswordR = $_POST["PasswordR"];

//reCaptcha
$Url = "https://www.google.com/recaptcha/api/siteverify";
$SecretKey = "---KEY---";
$Response = file_get_contents($Url."?secret=".$SecretKey."&response=".$_POST['response']."remoteip=".$_SERVER['REMOTE_ADDR']);
$Robot = json_decode($response);

$data = 0;

if(isset($Robot->success) AND $Robot->success==true){
    //OTHER CODE
}

else{
    //This code always runs (though this is only meant to happen if reCaptcha detects a robot.
    $data = 4;
        echo json_encode(["data"=>"$data"]);
?>
Thomas Smyth
  • 513
  • 1
  • 8
  • 34
  • Obviously I used my actual key in my test, however I removed it here for security reasons. – Thomas Smyth Nov 28 '16 at 12:50
  • 1
    I recommend trying to boil down the example to less code. Surely the issue doesn't take a complete code review to duplicate or understand. You'll get more expert advice if the example is more clinical and less tldr. – WEBjuju Nov 28 '16 at 12:59
  • @WEBjuju, yeh the code was a bit over the top for the question at hand. I've boiled it down so hopefully it will be a lot easier to understand. – Thomas Smyth Nov 28 '16 at 13:47

2 Answers2

1

Here, it is important to watch casing of your variables:

$Response = file_get_contents($Url."?secret=".$SecretKey."&response=".$_POST['response']."remoteip=".$_SERVER['REMOTE_ADDR']);
//   because variables are case sensitive...
$Robot = json_decode($Response);  // it is $Response, not $response

If that doesn't fix it, please update your question with the output this produces:

$Response = file_get_contents($Url."?secret=".$SecretKey."&response=".$_POST['response']."remoteip=".$_SERVER['REMOTE_ADDR']);
die('Response file: <pre>'.$Response);
$Robot = json_decode($Response);

also try be sure to urlencode() the vars you are sending to google:

$Response = file_get_contents($Url."?secret=".urlencode($SecretKey)."&response=".urlencode($_POST['response'])."remoteip=".urlencode($_SERVER['REMOTE_ADDR']));

but by far, you must

$Robot = json_decode($Response);  // and NOT $response

here is a screenshot showing how to get the output from the ajax call where you have die() in your php processing said ajax call:

enter image description here

BEST SOLUTION

Review this guide on how to install Google reCAPTCHA with PHP

WEBjuju
  • 4,597
  • 3
  • 20
  • 33
  • I've updated the variable case, though I think I may have already tried that after posting the question. I then tried your other piece of code, however, I get an error in Chrome console saying `Uncaught SyntaxError: Unexpected token R in JSON at position 0`, but no error in a log file. I believe that's not related to the reCaptcha, but the way you want to error created returned. – Thomas Smyth Nov 28 '16 at 14:55
  • 1
    you'll need to only put in that die() during this debugging - and to get the output of that debugging, you'll need to check the javascript console to see the result of the ajax call (so you can past that output for us here, pls) – WEBjuju Nov 28 '16 at 15:03
  • I have tried your edit to your anwer. The error outputted is `VM552:1 Uncaught SyntaxError: Unexpected token R in JSON at position 0(anonymous function) @ login.js:34l @ jquery.min.js:4fireWith @ jquery.min.js:4k @ jquery.min.js:6(anonymous function) @ jquery.min.js:6`. Alternatively, you could look at the console on my page here: http://thomas-smyth.co.uk/register.php Thanks for your help so far. – Thomas Smyth Nov 28 '16 at 15:10
  • well, no, your output from the ajax call is: { "success": false, "error-codes": [ "invalid-input-response" ] } – WEBjuju Nov 28 '16 at 15:14
  • please be sure to follow this guide https://developers.google.com/recaptcha/old/docs/php – WEBjuju Nov 28 '16 at 15:17
  • where is that message outputted too? The only thing I see in my console is the error message I previously listed. Without the `die()` the ajax returns 4, which displays "I don't like robots" from the javascript. – Thomas Smyth Nov 28 '16 at 15:18
  • 1
    my console is firebug in firefox. you can find these in the other browsers, but it find them all a pain compared to this. see how the carrot lets you open up the call to fncregister.php so you can choose the various tabs? the other browser consoles have something simliar...just dig around / or google around. the end issue here is that it just looks like it's not installed properly. follow the guide. https://developers.google.com/recaptcha/old/docs/php – WEBjuju Nov 28 '16 at 15:20
  • I'll try Firebug when I get home onto my home computer. It seems you linked to documentation for reCaptcha V1, rather than V2. I've had a look at the V2 documentation and find little guidance on how to actually verify the verification. – Thomas Smyth Nov 28 '16 at 15:31
  • 1
    yes, good point on the documentation. i think if you check into it, though, you'll see that somewhere you aren't grabbing that first call which is responding from google upon click of the reCAPTCHA. you can see in my screenshot that google responds with that "uvresp". you need that to pass back with your submission to verify. the response that i see when you die() out the processing php indicates that you're not passing that back in _POST['response']. – WEBjuju Nov 28 '16 at 15:34
  • I've installed Firebug and it works a treat, though I don't see the returned value from Google. Do you know where this value is returned? I guess I need to place it into the ajax call, however, I'm not sure what it's defined as etc. Again, the documentation for this seems to be lacking and it's hard to tell whether the stuff created by others if for V1 or V2 of reCaptcha. – Thomas Smyth Nov 28 '16 at 16:29
  • 1
    in firebug watch the console when you click "verify i'm a human"...you get the ajax call to recaptcha/api2/userverify...open that up and see that it looks like my screenshot. now, you need to be sure you are grabbing the response id/val/code (whatever they call it), and you need to put that in your form to submit. when php gets the submission, it takes the id/val/code and then goes into your verification call you are making within php. – WEBjuju Nov 28 '16 at 16:48
  • Ok, so `var Response = grecaptcha.getResponse();` seems to collect the that value when the reCaptcha is complete. I've now added this into the AJAX to contact the PHP file. It seems though, that something within the URL to reCaptcha to check everything is successful is wrong. I'm investigating into it now. – Thomas Smyth Nov 28 '16 at 17:22
  • 1
    great @thomasSmyth! you can do it! – WEBjuju Nov 28 '16 at 17:23
  • According to the documentation (https://developers.google.com/recaptcha/docs/verify) you need to send the information via POST not GET. Any suggestions on how this is done? – Thomas Smyth Nov 28 '16 at 17:36
  • yes, you can use php curl - http://stackoverflow.com/questions/2138527/php-curl-http-post-sample-code – WEBjuju Nov 28 '16 at 17:50
0

Not quite sure how I got it to work, but I did.

Firstly, I added a new variable "Response" into my Javascript and used the function listed in the documentation to retrieve the value of the key that is returned when the user proves they are not a robot. I added this variable into my AJAX call too, so that it is passed onto the PHP File, like so:

function Register(){
    var Forename = $("#txtForename" ).val();
    var Surname = $("#txtSurname" ).val();
    var Password = $("#txtPassword").val();
    var PasswordR = $("#txtPasswordR").val();
    var Response = grecaptcha.getResponse();
        $.post('functions/php/fncregister.php', {Forename: Forename, Surname: Surname, Password: Password, PasswordR: PasswordR, Response: Response}, function(data) {
            var returnValue = JSON.parse(data);
            if (returnValue['data'] == 0){
                $('#mdlInfo').html('<p>Your account has been created under the username: <strong><span id="spnUsername">'+returnValue['username']+'</span></strong>. You <strong>must</strong> remember this as you will require it to log into your account.</p><p>Your account has also been added to a moderation que. <strong>You must wait until a member of staff activates your account!</strong></p>');
                $("#mdlRegister").modal("show");
            }
            else if (returnValue['data'] == 1){
                $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">Passwords did not match!</p>');
            }
            else if (returnValue['data'] == 3){
                $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">An error occured when adding your details to the Database!</p>');
            }
            else if (returnValue['data'] == 4){
                $('#divError').html('<p class="text-center text-danger bg-danger" id="pUPInc">I don\'t like Robots!</p>');
            }
        });
}

In my PHP file I removed the user IP address from the URL post as it's optional according to documentation (not sure on the benefit of doing it though). Google then returns the information about the request and if successful then the item "success" with be true in my code and thus proceed onto generating the account:

$Url = "https://www.google.com/recaptcha/api/siteverify";
$SecretKey = "---KEY---";
$Response = file_get_contents($Url."?secret=".$SecretKey."&response=".$_POST['Response']);
$Robot = json_decode($Response);

$data = 0;

if(isset($Robot->success) AND $Robot->success==true){

I didn't use POST in the end, but used GET instead. I'm sure there's some security benefit as it will hide the secret key, so I will look into it shortly.

Thanks to @WEBjuju and my mate "Bridge Troll" for their assistance. I couldn't have done it without either of them.

Thomas Smyth
  • 513
  • 1
  • 8
  • 34