Skip to content

Instantly share code, notes, and snippets.

@Kubo2
Created December 20, 2019 12:31
Show Gist options
  • Save Kubo2/bc4b85b809ffa50c9cc8c866d60b975b to your computer and use it in GitHub Desktop.
Save Kubo2/bc4b85b809ffa50c9cc8c866d60b975b to your computer and use it in GitHub Desktop.
Implement Google reCAPTCHA v3 backend+advice

Resources

Obviously, you will need to link the api.js from Google in your form.html to work with the grecaptcha object.

A comprehensive guide (with some errors though):

Google Codelab (reCAPTCHA v2):

Before doing any of this, you need the site key-secret key pair from Google for that particular version of reCAPTCHA, e.g. v3.

<form action='/verify.php' method='post'>
<input type='submit'>
<input type='hidden' name='recaptcha-token'>
</form>
document.forms[0].onsubmit = function (event) {
event.preventDefault();
grecaptcha.execute(siteKey, { action: actionLabel }).then(function (token) {
event.target['recaptcha-token'].value = token
event.target.submit()
})
}
<?php
/**
* This is a library based on an original Google code that handles reCAPTCHA v3.
*
* @author Jakub KUBÍČEK <jakub.david.kubicek@gmail.com>
*/
/**
* Represents a reCAPTCHA pool of successfuly completed challenges.
*/
final class ReCaptcha
{
private $secret;
/**
* @param string $secret shared secret between site and ReCAPTCHA server.
*/
public function __construct($secret)
{
$this->secret = $secret;
}
/**
* Ask the pool if completed challenge token is valid.
*
* @param string user's response token for the reCAPTCHA challenge
* @return bool
*/
final public function valid($response)
{
return !empty($response)
&& json_decode($json = $this->apiResponse($response), TRUE)['success']
&& max(.4, json_decode($json, TRUE)['score']) !== .4; // above threshold
}
/**
* @return string URL-encoded key-value pair
*/
private function urlencoded($name, $value)
{
return rawurlencode($name) . '=' . rawurlencode($value);
}
/**
* @param array(string => string, ...)
* @return string URL-encoded query string of key-value pairs
*/
private function qsencoded(array $kvPairs)
{
$pieces = [];
foreach($kvPairs as $k => $v) {
$pieces[] = $this->urlencoded($k, $v);
}
return implode('&', $pieces);
}
/**
* Submits a HTTP GET to the reCAPTCHA server.
*
* @param array user's response token for the reCAPTCHA challenge
* @return string JSON response
*/
private function apiResponse($response)
{
return file_get_contents(
'https://www.google.com/recaptcha/api/siteverify',
FALSE,
stream_context_create([
'http' => [
'method' => 'POST',
'content' => $this->qsencoded(['response' => $response, 'secret' => $this->secret]),
'header' => 'Content-Type: application/x-www-form-urlencoded'
]
])
);
}
}
<?php
echo (new ReCaptcha($siteSecret))->valid($_POST['recaptcha-token']) ? 'User unlikely to be a bot' : 'User is very likely a bot';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment