Google reCaptcha in Web API 2 c#

10,480

Solution 1

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.

Solution 2

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)

Solution 3

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;
        }
Share:
10,480
Samy Sammour
Author by

Samy Sammour

My experiences are deep in Web development with .NET. I am a computer science engineer and a Microsoft Certified Solution Developer (MCSD), MCP ASP.NET MVC, MS Front-End. I work as a full-stack senior web developer. I have experience in using client-side scripting dealing with Angular, Typescript, Redux and Kendo. I have developed in the last few years my Windows Azure cloud skills: Web Services, Storage, Azure B2C, Elastic Search, CosmosDb, KeyVault, ... I am very fascinated about Domain-Driven Design which I would love to learn more about it.

Updated on June 19, 2022

Comments

  • Samy Sammour
    Samy Sammour almost 2 years

    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