1

I am trying to implement reCAPTCHA validation via Marketing Cloud - cloud page.

I have used this guide to do that: https://ampscript.xyz/how-tos/how-to-implement-google-recaptcha-on-marketing-cloud-forms/

What I want to do is to create a post request instead of use the action form property.

My Clint side script:

<!doctype html>
<html>
<head>
 <meta charset="utf-8">
 <title></title>
 <meta name="description" content="">
 <meta name="viewport" content="width=device-width, initial-scale=1">

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

<body>



<form id="form" >
    <label>Email: </label>
    <input type="email" name="EmailAddress">
    <div 
        class="g-recaptcha" 
        data-sitekey="XXXXXXXXXXXXXXXXXXXXXX" 
        data-callback="grecaptchaCallback" 
        data-size="invisible"
    ></div>
    <br>
    <button>Send</button>
</form>


<script>
    var form = document.getElementById('form');

    form.addEventListener('submit', grecaptchaValidate);

    function grecaptchaCallback() {
        return new Promise(function (resolve, reject) {
            if (grecaptcha.getResponse() !== '') {
                var x=grecaptcha.getResponse();
                console.log(x);
                var xhttp = new XMLHttpRequest();
                xhttp.open("POST", "https://pub.s7.exacttarget.com/jnmlkgsfquv", true);
                xhttp.setRequestHeader("Content-type",  'text/html',['Accept-Encoding'], ['identity'] );
                xhttp.send();
                http.onreadystatechange =  function() {
        if (this.readyState == 4 && this.status == 200) {
        
        var response=this.responseText;
        console.log(response);
        response=response.split("<script>");
        console.log(response);
        console.log(response[0].trim());
    }

}
            }
            grecaptcha.reset();
        })
    }

    function grecaptchaValidate(e) {
        e.preventDefault();
        grecaptcha.execute();
    }
</script>


</body>
</html>
    </script>
</body>
</html>

And this is my server-side script:

<script runat="server">
 
    Platform.Load("core", "1.1.1");

    try {

        var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
        var secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var payload = "secret=" + secret + "&response=" + g_recaptcha_response;
  var contentType = "application/x-www-form-urlencoded";
  var endpoint = "https://www.google.com/recaptcha/api/siteverify";
        var req = HTTP.Post(endpoint, contentType, payload);

        if (req.StatusCode == 200) {

            var resp = Platform.Function.ParseJSON(String(req.Response));

            if (!resp.success) throw "Wrong reCAPTCHA";

        } else {
            throw "reCAPTCHA API error";
        }

        /// DO SOMETHING

        Write(Stringify(resp));

    } catch (error) {
        Write(Stringify({ status: "Error", message: error }));
    }

</script>

The error I get when I send the request is:

{"status":"Error","message":"Wrong reCAPTCHA"}




<script>(function(a,m,i,g,o,s){o=a.createElement(g);s=a.getElementsByTagName(i)[0];o.src=m.origin+m.pathname+"/_t?eventType=CLOUDPAGESVISIT";o.width=0;o.height=0;o.style.display="none";s.appendChild(o);})(document,window.location,"body","img");</script>
    <script src="https:&#x2F;&#x2F;7231513.collect.igodigital.com&#x2F;collect.js"></script>
    <script>
        if (_etmc && typeof _etmc.push === 'function') {
            _etmc.push(['setOrgId', '7231513']);
            _etmc.push(['trackPageView']);
        }
    </script>

Another conclusion I came to- If I insert manually the value that I received from the client-side from x object (the grecaptcha.getResponse() ) The response correct:

 {"success":true,"challenge_ts":"2020-07-29T09:30:03Z","hostname":"pub.s7.exacttarget.com"}

I would love to get an idea of how I create the request from the client-side to the server-side page according to post I am initiating?

Is there anything I'm missing? Or maybe I'm not working correctly?

Edit:

The problem was with the payload at server-side page, because the variable g_recaptcha_response was null.

My workaround is to catch the variable with query string variable:


%%[
  set @x = RequestParameter("x")
]%%
<script runat="server">
 
    Platform.Load("core", "1.1.1");
  var x = Variable.GetValue("@x");  
 

    try {

 
      //  var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
      
        var secret = "XXXXXXXXXXXXXXXXXXXXXXXXX";
        var payload = "secret=" + secret + "&response=" + x;
  var contentType = "application/x-www-form-urlencoded";
  var endpoint = "https://www.google.com/recaptcha/api/siteverify";
        var req = HTTP.Post(endpoint, contentType, payload);

        if (req.StatusCode == 200) {

            var resp = Platform.Function.ParseJSON(String(req.Response));

            if (!resp.success) throw "Wrong reCAPTCHA";

        } else {
            throw "reCAPTCHA API error";
        }

        /// DO SOMETHING

        Write(Stringify(resp));

    } catch (error) {
        Write(Stringify({ status: "Error", message: error }));
    }

</script>

Because there is no way to catch URL data on SSJS I using AMPscript to catch x and pass it to payload, now I get a success response.

But I'm not sure if there have any security problem in this way.

  • There should be error description in req.Response on server side. Can you add example response to see what error is causing this. There's a list of possible values that are returned on developers.google.com/recaptcha/docs/verify – Mateusz Bartkowiak Jul 29 at 14:21
  • I'm not getting one of those mistakes. I get another error and I mentioned it in post. {"status":"Error","message":"Wrong reCAPTCHA"} – nadav_z Jul 30 at 6:13
  • That's the error you're throwing yourself when response is not successful. I'm talking about error reason returned by google inside resp variable – Mateusz Bartkowiak Jul 30 at 9:56
  • I was able to solve the problem. Thanks for your comments, they helped me understand the source of the problem. moreover, I edited my question and write my solution. You welcome to look and say your opinion. – nadav_z Aug 1 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.