5

I have an ASP.NET Web API 2 Project. I am trying to read Google Captcha from the form. I tried this Code:

    public string Post(FoundingRequest model)
    {
        var response = Request["g-recaptcha-response"];
        string secretKey = "my key";
        var client = new WebClient();
        var result = client.DownloadString(
        $"https://www.google.com/recaptcha/api/siteverify?secret={secretKey}&response={response}");
        var obj = JObject.Parse(result);
        model.Captcha = (bool)obj.SelectToken("success");
        ....
    }

but I am receiving an Error on the first line:

Cannot apply indexing with [] to an expression of type 'HttpRequestMessage'

why? and how to solve it? thank you

Samy Sammour
  • 2,298
  • 2
  • 31
  • 66

4 Answers4

6

That method's body for me works fine:

 const string secretKey = "YOUR KEY";
            string responseFromServer = "";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + response);

            using (WebResponse resp = req.GetResponse())
            using (Stream dataStream = resp.GetResponseStream())
            {
                if (dataStream != null)
                {
                    using (StreamReader reader = new StreamReader(dataStream))
                    {
                        // Read the content.
                        responseFromServer = reader.ReadToEnd();
                    }
                }
            }

            dynamic jsonResponse = new JavaScriptSerializer().DeserializeObject(responseFromServer);

            return jsonResponse == null || bool.Parse(jsonResponse["success"].ToString());

Update

Regarding the comment, it can be checked on the client side

var response = window.grecaptcha.getResponse()

And then pass this variable to Web API

This is part of my client script:

      if (typeof window.grecaptcha != 'undefined') {
        var capResponse = window.grecaptcha.getResponse();

        if (!capResponse || capResponse.length === 0) {
            user.isCaptchaPassed = false;
            //alert("Captcha not Passed");
            return false;
        }

        user.gReCaptcha = capResponse;
    }

"user" is JS object created before, which passed through JS to server. (AJAX call)

SouXin
  • 1,565
  • 11
  • 17
2

I found the answer, I created a hidden input with a certain name and updated its value on Captcha call back. Code:

   <input type="hidden" value="" id="recaptcha" name="recaptcha" />
   <div class="g-recaptcha" data-callback="imNotARobot" data-sitekey="key"></div>

and the Javascript is:

<script type="text/javascript">
    var imNotARobot = function () {
       $("#recaptcha").val(grecaptcha.getResponse());
    };
</script>

server side:

public string Recaptcha { get; set; }

and the model binder does all the work.

Samy Sammour
  • 2,298
  • 2
  • 31
  • 66
2

Here's how I did it. I don't use the ChallangeTs so I didn't bother trying to figure out why it wasn't converting to DateTime properly. Maybe someone else has that solved.

   public class ReCaptchaResponse
        {
            public bool Success;
            public string ChallengeTs;
            public string Hostname;
            public object[] ErrorCodes;
        }

        [HttpPost]
        [Route("captcha")]
        public bool Captcha([FromBody] string token)
        {
            bool isHuman = true;

            try
            {
                string secretKey = ConfigurationManager.AppSettings["reCaptchaPrivateKey"];
                Uri uri = new Uri("https://www.google.com/recaptcha/api/siteverify" +
                                  $"?secret={secretKey}&response={token}");
                HttpWebRequest request = WebRequest.CreateHttp(uri);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = 0;
                HttpWebResponse response = (HttpWebResponse) request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream);
                string result = streamReader.ReadToEnd();
                ReCaptchaResponse reCaptchaResponse = JsonConvert.DeserializeObject<ReCaptchaResponse>(result);
                isHuman = reCaptchaResponse.Success;
            }
            catch (Exception ex)
            {
                Trace.WriteLine("reCaptcha error: " + ex);
            }

            return isHuman;
        }
INFOequipt
  • 29
  • 5
-1

I assume this request is coming from a form, change this:

var response = Request["g-recaptcha-response"];

To this:

var response = Request.Form["g-Recaptcha-Response"];

Also Change this:

var result = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret={secretKey}&response={response}");

To this:

var result = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, response));
Kyle
  • 1,013
  • 8
  • 16
  • please read the question again. the problem is with : var response = Request["g-recaptcha-response"]; the first line with the error message that mention in the question – Samy Sammour Apr 10 '17 at 15:44
  • There is no Form in Web Api 2 Request – Samy Sammour Apr 10 '17 at 16:20
  • Where is the ReCaptcha? On an MVC page? You will need to validate the ReCaptcha in your MVC controller then cal you API. – Kyle Apr 10 '17 at 16:22
  • it is on pure html and javascript. no server side – Samy Sammour Apr 10 '17 at 16:24
  • It is not going to work like that. You need to perform a server side check within the web app. As the API is unable to glean the other information it needs from the markup such as the sitekey. – Kyle Apr 10 '17 at 16:38
  • and if I don't have a service side in my html code, what to do? can I check it using JavaScript? – Samy Sammour Apr 10 '17 at 16:45
  • No, if you could check it client side it would be defeatable by hackers, as they could bypass it. I am not aware of a way to do this straight to WebAPI. – Kyle Apr 10 '17 at 16:53
  • Here you go check out this article on SO that shows some way to work with it with JS. http://stackoverflow.com/questions/27902539/how-can-i-validate-google-recaptcha-v2-using-javascript-jquery – Kyle Apr 10 '17 at 16:56
  • The part about string interpolation $"..." is wrong. String interpolation is just syntatic sugar for String.Format(). You've confused it with string literals @"" – Brent Mar 02 '18 at 18:42