Google reCAPTCHA: How to get user response and validate in the server side?
The cool thing about the new Google Recaptcha is that the validation is now completely encapsulated in the widget. That means, that the widget will take care of asking questions, validating responses all the way till it determines that a user is actually a human, only then you get a g-recaptcha-response value.
But that does not keep your site safe from HTTP client request forgery.
Anyone with HTTP POST knowledge could put random data inside of the g-recaptcha-response form field, and foll your site to make it think that this field was provided by the google widget. So you have to validate this token.
In human speech it would be like,
- Your Server: Hey Google, there's a dude that tells me that he's not a robot. He says that you already verified that he's a human, and he told me to give you this token as a proof of that.
- Google: Hmm... let me check this token... yes I remember this dude I gave him this token... yeah he's made of flesh and bone let him through.
- Your Server: Hey Google, there's another dude that tells me that he's a human. He also gave me a token.
- Google: Hmm... it's the same token you gave me last time... I'm pretty sure this guy is trying to fool you. Tell him to get off your site.
Validating the response is really easy. Just make a GET Request to
https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address
And replace the response_string with the value that you earlier got by the g-recaptcha-response field.
You will get a JSON Response with a success field.
More information here: https://developers.google.com/recaptcha/docs/verify
Edit: It's actually a POST, as per documentation here.
A method I use in my login servlet to verify reCaptcha responses. Uses classes from the java.json package. Returns the API response in a JsonObject.
Check the success field for true or false
private JsonObject validateCaptcha(String secret, String response, String remoteip)
{
JsonObject jsonObject = null;
URLConnection connection = null;
InputStream is = null;
String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String url = "https://www.google.com/recaptcha/api/siteverify";
try {
String query = String.format("secret=%s&response=%s&remoteip=%s",
URLEncoder.encode(secret, charset),
URLEncoder.encode(response, charset),
URLEncoder.encode(remoteip, charset));
connection = new URL(url + "?" + query).openConnection();
is = connection.getInputStream();
JsonReader rdr = Json.createReader(is);
jsonObject = rdr.readObject();
} catch (IOException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
return jsonObject;
}
Hi curious you can validate your google recaptcha at client side also 100% work for me to verify your google recaptcha just see below code
This code at the html body:
<div class="g-recaptcha" id="rcaptcha" style="margin-left: 90px;" data-sitekey="my_key"></div>
<span id="captcha" style="margin-left:100px;color:red" />
This code put at head section on call get_action(this)
method form button:
function get_action(form) {
var v = grecaptcha.getResponse();
if(v.length == 0)
{
document.getElementById('captcha').innerHTML="You can't leave Captcha Code empty";
return false;
}
if(v.length != 0)
{
document.getElementById('captcha').innerHTML="Captcha completed";
return true;
}
}
Here is complete demo code to understand client side and server side process. you can copy paste it and just replace google site key and google secret key.
<?php
if(!empty($_REQUEST))
{
// echo '<pre>'; print_r($_REQUEST); die('END');
$post = [
'secret' => 'Your Secret key',
'response' => $_REQUEST['g-recaptcha-response'],
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);
echo '<pre>'; print_r($server_output); die('ss');
}
?>
<html>
<head>
<title>reCAPTCHA demo: Explicit render for multiple widgets</title>
<script type="text/javascript">
var site_key = 'Your Site key';
var verifyCallback = function(response) {
alert(response);
};
var widgetId1;
var widgetId2;
var onloadCallback = function() {
// Renders the HTML element with id 'example1' as a reCAPTCHA widget.
// The id of the reCAPTCHA widget is assigned to 'widgetId1'.
widgetId1 = grecaptcha.render('example1', {
'sitekey' : site_key,
'theme' : 'light'
});
widgetId2 = grecaptcha.render(document.getElementById('example2'), {
'sitekey' : site_key
});
grecaptcha.render('example3', {
'sitekey' : site_key,
'callback' : verifyCallback,
'theme' : 'dark'
});
};
</script>
</head>
<body>
<!-- The g-recaptcha-response string displays in an alert message upon submit. -->
<form action="javascript:alert(grecaptcha.getResponse(widgetId1));">
<div id="example1"></div>
<br>
<input type="submit" value="getResponse">
</form>
<br>
<!-- Resets reCAPTCHA widgetId2 upon submit. -->
<form action="javascript:grecaptcha.reset(widgetId2);">
<div id="example2"></div>
<br>
<input type="submit" value="reset">
</form>
<br>
<!-- POSTs back to the page's URL upon submit with a g-recaptcha-response POST parameter. -->
<form action="?" method="POST">
<div id="example3"></div>
<br>
<input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer>
</script>
</body>
</html>