Skip to content

Commit 062198e

Browse files
committed
Backwards compatible update to verify method
1 parent 1d93893 commit 062198e

File tree

9 files changed

+100
-114
lines changed

9 files changed

+100
-114
lines changed

ARCHITECTURE.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# Architecture
22

33
The general pattern of usage is to instantiate the `ReCaptcha` class with your
4-
secret key, specify any additional validation rules, and then call
5-
`verifyAndValidate()` with the reCAPTCHA response and user's IP address. For
6-
example:
4+
secret key, specify any additional validation rules, and then call `verify()`
5+
with the reCAPTCHA response and user's IP address. For example:
76

87
```php
98
<?php
109
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
1110
$resp = $recaptcha->setExpectedHostname('recaptcha-demo.appspot.com')
12-
->verifyAndValidate($gRecaptchaResponse, $remoteIp);
11+
->verify($gRecaptchaResponse, $remoteIp);
1312
if ($resp->isSuccess()) {
1413
// Verified!
1514
} else {

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ functionality into your frontend.
6464
This library comes in when you need to verify the user's response. On the PHP
6565
side you need the response from the reCAPTCHA service and secret key from your
6666
credentials. Instantiate the `ReCaptcha` class with your secret key, specify any
67-
additional validation rules, and then call `verifyAndValidate()` with the
68-
reCAPTCHA response and user's IP address. For example:
67+
additional validation rules, and then call `verify()` with the reCAPTCHA
68+
response and user's IP address. For example:
6969

7070
```php
7171
<?php
7272
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
7373
$resp = $recaptcha->setExpectedHostname('recaptcha-demo.appspot.com')
74-
->verifyAndValidate($gRecaptchaResponse, $remoteIp);
74+
->verify($gRecaptchaResponse, $remoteIp);
7575
if ($resp->isSuccess()) {
7676
// Verified!
7777
} else {
@@ -93,16 +93,16 @@ The following methods are available:
9393
- `setChallengeTimeout($timeoutSeconds)`: set a timeout between the user passing
9494
the reCAPTCHA and your server processing it.
9595

96-
Each of the `set`\*`()` methods return the `ReCaptcha` instance so you can chain them
97-
together. For example:
96+
Each of the `set`\*`()` methods return the `ReCaptcha` instance so you can chain
97+
them together. For example:
9898

9999
```php
100100
<?php
101101
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
102102
$resp = $recaptcha->setExpectedHostname('recaptcha-demo.appspot.com')
103103
->setExpectedAction('homepage')
104104
->setScoreThreshold(0.5)
105-
->verifyAndValidate($gRecaptchaResponse, $remoteIp);
105+
->verify($gRecaptchaResponse, $remoteIp);
106106

107107
if ($resp->isSuccess()) {
108108
// Verified!

examples/recaptcha-v2-checkbox-explicit.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@
8989
// its use with URLs, then you can use the alternative request method instead.
9090
// This makes use of fsockopen() instead.
9191
// $recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\SocketPost());
92-
9392
// Make the call to verify the response and also pass the user's IP address
94-
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
93+
$resp = $recaptcha->setExpectedHostname($_SERVER['SERVER_NAME'])
94+
->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
9595

9696
if ($resp->isSuccess()):
9797
// If the response is a success, that's it!

examples/recaptcha-v2-checkbox.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@
9191
// $recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\SocketPost());
9292

9393
// Make the call to verify the response and also pass the user's IP address
94-
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
95-
94+
$resp = $recaptcha->setExpectedHostname($_SERVER['SERVER_NAME'])
95+
->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
9696
if ($resp->isSuccess()):
9797
// If the response is a success, that's it!
9898
?>

examples/recaptcha-v2-invisible.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@
9191
// $recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\SocketPost());
9292

9393
// Make the call to verify the response and also pass the user's IP address
94-
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
95-
94+
$resp = $recaptcha->setExpectedHostname($_SERVER['SERVER_NAME'])
95+
->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
9696
if ($resp->isSuccess()):
9797
// If the response is a success, that's it!
9898
?>

examples/recaptcha-v3-request-scores.php

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,29 +81,27 @@
8181
?>
8282
<p>reCAPTCHA will provide a score for this request.</p>
8383
<ol id="recaptcha-steps">
84-
<li>reCAPTCHA script it loading.</li>
84+
<li class="step0">reCAPTCHA script loading</li>
85+
<li style="display:none" class="step1"><kbd>grecaptcha.ready()</kbd> fired, calling <pre>grecaptcha.execute('<?php echo $siteKey; ?>', {action: 'homepage'})'</pre></li>
86+
<li style="display:none" class="step2">Received token from reCAPTCHA service, sending to our backend with <kbd>fetch('/recaptcha-v3-verify.php?token='+<span class="token">123</span>)</kbd></li>
87+
<li style="display:none" class="step3">Received response from our backend: <pre class="response">response</pre></li>
8588
</ol>
8689
<p><a href="/recaptcha-v3-request-scores.php">⟳ Try again</a></p>
8790

8891
<script src="https://www.google.com/recaptcha/api.js?render=<?php echo $siteKey; ?>"></script>
8992
<script>
9093
const steps = document.getElementById('recaptcha-steps');
9194
grecaptcha.ready(function() {
92-
93-
const showSending = document.createElement('li');
94-
showSending.appendChild(document.createTextNode('Calling grecaptcha.execute(\'*siteKey*\', {action: \'homepage\'})'));
95-
steps.appendChild(showSending);
96-
95+
document.querySelector('.step1').style.display = 'list-item';
9796
grecaptcha.execute('<?php echo $siteKey; ?>', {action: 'homepage'}).then(function(token) {
98-
99-
const showSending = document.createElement('li');
100-
showSending.appendChild(document.createTextNode('Sending token to our backend to verify'));
101-
steps.appendChild(showSending);
97+
document.querySelector('.token').innerHTML = token;
98+
document.querySelector('.step2').style.display = 'list-item';
10299

103100
fetch('/recaptcha-v3-verify.php?token='+token).then(function(response) {
104-
const showSending = document.createElement('li');
105-
showSending.appendChild(document.createTextNode('Received verification from our backend'));
106-
steps.appendChild(showSending);
101+
response.json().then(function(data) {
102+
document.querySelector('.response').innerHTML = JSON.stringify(data);
103+
document.querySelector('.step3').style.display = 'list-item';
104+
});
107105
});
108106
});
109107
});

examples/recaptcha-v3-verify.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

4040
// Effectively we're providing an API endpoint here that will accept the token, verify it, and return the action / score to the page
4141
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
42-
$resp = $recaptcha->verify($_GET['token'], $_SERVER['REMOTE_ADDR']);
43-
header('Content-type:application/json');
42+
$resp = $recaptcha->setExpectedHostname($_SERVER['SERVER_NAME'])
43+
->setExpectedAction('homepage')
44+
->setScoreThreshold(0.5)
45+
->verify($_GET['token'], $_SERVER['REMOTE_ADDR']);header('Content-type:application/json');
4446
echo json_encode($resp->toArray());

src/ReCaptcha/ReCaptcha.php

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public function __construct($secret, RequestMethod $requestMethod = null)
125125

126126
/**
127127
* Calls the reCAPTCHA siteverify API to verify whether the user passes
128-
* CAPTCHA test.
128+
* CAPTCHA test and additionally runs any specified additional checks
129129
*
130130
* @param string $response The user response token provided by reCAPTCHA, verifying the user on your site.
131131
* @param string $remoteIp The end user's IP address.
@@ -141,11 +141,50 @@ public function verify($response, $remoteIp = null)
141141

142142
$params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION);
143143
$rawResponse = $this->requestMethod->submit($params);
144-
return Response::fromJson($rawResponse);
144+
$initialResponse = Response::fromJson($rawResponse);
145+
$validationErrors = array();
146+
147+
if (isset($this->hostname) && strcasecmp($this->hostname, $initialResponse->getHostname()) !== 0) {
148+
$validationErrors[] = self::E_HOSTNAME_MISMATCH;
149+
}
150+
151+
if (isset($this->apkPackageName) && strcasecmp($this->apkPackageName, $initialResponse->getApkPackageName()) !== 0) {
152+
$validationErrors[] = self::E_APK_PACKAGE_NAME_MISMATCH;
153+
}
154+
155+
if (isset($this->action) && strcasecmp($this->action, $initialResponse->getAction()) !== 0) {
156+
$validationErrors[] = self::E_ACTION_MISMATCH;
157+
}
158+
159+
if (isset($this->threshold) && $this->threshold > $initialResponse->getScore()) {
160+
$validationErrors[] = self::E_SCORE_THRESHOLD_NOT_MET;
161+
}
162+
163+
if (isset($this->timeoutSeconds)) {
164+
$challengeTs = strtotime($initialResponse->getChallengeTs());
165+
166+
if ($challengeTs > 0 && time() - $challengeTs > $this->timeoutSeconds) {
167+
$validationErrors[] = self::E_CHALLENGE_TIMEOUT;
168+
}
169+
}
170+
171+
if (empty($validationErrors)) {
172+
return $initialResponse;
173+
}
174+
175+
return new Response(
176+
false,
177+
array_merge($initialResponse->getErrorCodes(), $validationErrors),
178+
$initialResponse->getHostname(),
179+
$initialResponse->getChallengeTs(),
180+
$initialResponse->getApkPackageName(),
181+
$initialResponse->getScore(),
182+
$initialResponse->getAction()
183+
);
145184
}
146185

147186
/**
148-
* Provide a hostname to match against in verifyAndValidate()
187+
* Provide a hostname to match against in verify()
149188
* This should be without a protocol or trailing slash, e.g. www.google.com
150189
*
151190
* @param string $hostname Expected hostname
@@ -158,7 +197,7 @@ public function setExpectedHostname($hostname)
158197
}
159198

160199
/**
161-
* Provide an APK package name to match against in verifyAndValidate()
200+
* Provide an APK package name to match against in verify()
162201
*
163202
* @param string $apkPackageName Expected APK package name
164203
* @return ReCaptcha Current instance for fluent interface
@@ -170,7 +209,7 @@ public function setExpectedApkPackageName($apkPackageName)
170209
}
171210

172211
/**
173-
* Provide an action to match against in verifyAndValidate()
212+
* Provide an action to match against in verify()
174213
* This should be set per page.
175214
*
176215
* @param string $action Expected action
@@ -183,7 +222,7 @@ public function setExpectedAction($action)
183222
}
184223

185224
/**
186-
* Provide a threshold to meet or exceed in verifyAndValidate()
225+
* Provide a threshold to meet or exceed in verify()
187226
* Threshold should be a float between 0 and 1 which will be tested as response >= threshold.
188227
*
189228
* @param float $threshold Expected threshold
@@ -196,7 +235,7 @@ public function setScoreThreshold($threshold)
196235
}
197236

198237
/**
199-
* Provide a timeout in seconds to test against the challenge timestamp in verifyAndValidate()
238+
* Provide a timeout in seconds to test against the challenge timestamp in verify()
200239
*
201240
* @param int $timeoutSeconds Expected hostname
202241
* @return ReCaptcha Current instance for fluent interface
@@ -206,56 +245,4 @@ public function setChallengeTimeout($timeoutSeconds)
206245
$this->timeoutSeconds = $timeoutSeconds;
207246
return $this;
208247
}
209-
210-
/**
211-
* Calls the reCAPTCHA siteverify API to verify whether the user passes
212-
* CAPTCHA test and additionally runs any specified additional checks
213-
*
214-
* @param string $response The user response token provided by reCAPTCHA, verifying the user on your site.
215-
* @param string $remoteIp The end user's IP address.
216-
* @return Response Response from the service.
217-
*/
218-
public function verifyAndValidate($response, $remoteIp = null)
219-
{
220-
$initialResponse = $this->verify($response, $remoteIp);
221-
$validationErrors = array();
222-
223-
if (isset($this->hostname) && strcasecmp($this->hostname, $initialResponse->getHostname()) !== 0) {
224-
$validationErrors[] = self::E_HOSTNAME_MISMATCH;
225-
}
226-
227-
if (isset($this->apkPackageName) && strcasecmp($this->apkPackageName, $initialResponse->getApkPackageName()) !== 0) {
228-
$validationErrors[] = self::E_APK_PACKAGE_NAME_MISMATCH;
229-
}
230-
231-
if (isset($this->action) && strcasecmp($this->action, $initialResponse->getAction()) !== 0) {
232-
$validationErrors[] = self::E_ACTION_MISMATCH;
233-
}
234-
235-
if (isset($this->threshold) && $this->threshold > $initialResponse->getScore()) {
236-
$validationErrors[] = self::E_SCORE_THRESHOLD_NOT_MET;
237-
}
238-
239-
if (isset($this->timeoutSeconds)) {
240-
$challengeTs = strtotime($initialResponse->getChallengeTs());
241-
242-
if ($challengeTs > 0 && time() - $challengeTs > $this->timeoutSeconds) {
243-
$validationErrors[] = self::E_CHALLENGE_TIMEOUT;
244-
}
245-
}
246-
247-
if (empty($validationErrors)) {
248-
return $initialResponse;
249-
}
250-
251-
return new Response(
252-
false,
253-
array_merge($initialResponse->getErrorCodes(), $validationErrors),
254-
$initialResponse->getHostname(),
255-
$initialResponse->getChallengeTs(),
256-
$initialResponse->getApkPackageName(),
257-
$initialResponse->getScore(),
258-
$initialResponse->getAction()
259-
);
260-
}
261248
}

0 commit comments

Comments
 (0)