Skip to content

Commit ab923e0

Browse files
thoughtpolicethoughtpolice
authored and
thoughtpolice
committedFeb 3, 2017
Implement new reCAPTCHA interface
Summary: Fixes T12195. For the past few years, Recaptcha (now part of Google) has supported a new, "no captcha" one-click user interface. This new UI is stable, doesn't require any typing or reading words, and can even work without JavaScript (if the administrator enables it on the Recaptcha side). Furthermore, the new Recaptcha has a completely trivial API that can be dealt with in a few lines of code. Thus, the external `recaptcha` php library is now gone. This API is a complete replacement for the old one, and does not require any upgrade path for users or Phabricator administrators - public and secret keys for the "new" Recaptcha UI are the exact same as the "classic" Recaptcha. Any old Recaptcha keys for a domain will continue to work. Note that Google is currently testing Yet Another new Captcha API, called "Invisible reCAPTCHA", that will not require user interaction at all. In fact, the user will not even be aware there //is even a captcha form//, as far as I understand. However, this new API is 1) in beta, 2) requires new Recaptcha keys (so it cannot be a drop-in replacement), and 3) requires more drastic API changes, as form submission buttons must instead invoke JavaScript code, rather than a token being passed along with the form submission. This would require far more extensive changes to the controllers. Maybe when it's several years old, it can be considered. Signed-off-by: Austin Seipp <aseipp@pobox.com> Test Plan: Created a brand-new Phabricator installation, saw the new Captcha UI on administrator sign up. Logged out, made 5 invalid login attempts, and saw the new Captcha UI. Reworked the conditional to invert the condition, etc to test and make sure the API responded properly. Reviewers: epriestley, #blessed_reviewers, chad Reviewed By: epriestley, #blessed_reviewers Subscribers: avivey, Korvin Maniphest Tasks: T12195 Differential Revision: https://secure.phabricator.com/D17304
1 parent 4274381 commit ab923e0

File tree

4 files changed

+28
-330
lines changed

4 files changed

+28
-330
lines changed
 

‎externals/recaptcha/LICENSE

-22
This file was deleted.

‎externals/recaptcha/recaptchalib.php

-277
This file was deleted.

‎src/applications/config/option/PhabricatorRecaptchaConfigOptions.php

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function getOptions() {
2323

2424
return array(
2525
$this->newOption('recaptcha.enabled', 'bool', false)
26+
->setLocked(true)
2627
->setBoolOptions(
2728
array(
2829
pht('Enable Recaptcha'),
@@ -35,6 +36,7 @@ public function getOptions() {
3536
'failed login attempts. This hinders brute-force attacks against '.
3637
'user passwords. For more information, see http://recaptcha.net/')),
3738
$this->newOption('recaptcha.public-key', 'string', null)
39+
->setLocked(true)
3840
->setDescription(
3941
pht('Recaptcha public key, obtained by signing up for Recaptcha.')),
4042
$this->newOption('recaptcha.private-key', 'string', null)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
<?php
22

3-
/**
4-
*
5-
* @phutil-external-symbol function recaptcha_get_html
6-
* @phutil-external-symbol function recaptcha_check_answer
7-
*/
83
final class AphrontFormRecaptchaControl extends AphrontFormControl {
94

105
protected function getCustomControlClass() {
@@ -19,44 +14,44 @@ public static function isRecaptchaEnabled() {
1914
return PhabricatorEnv::getEnvConfig('recaptcha.enabled');
2015
}
2116

22-
private static function requireLib() {
23-
$root = phutil_get_library_root('phabricator');
24-
require_once dirname($root).'/externals/recaptcha/recaptchalib.php';
25-
}
26-
2717
public static function hasCaptchaResponse(AphrontRequest $request) {
28-
return $request->getBool('recaptcha_response_field');
18+
return $request->getBool('g-recaptcha-response');
2919
}
3020

3121
public static function processCaptcha(AphrontRequest $request) {
3222
if (!self::isRecaptchaEnabled()) {
3323
return true;
3424
}
3525

36-
self::requireLib();
26+
$uri = 'https://www.google.com/recaptcha/api/siteverify';
27+
$params = array(
28+
'secret' => PhabricatorEnv::getEnvConfig('recaptcha.private-key'),
29+
'response' => $request->getStr('g-recaptcha-response'),
30+
'remoteip' => $request->getRemoteAddress(),
31+
);
3732

38-
$challenge = $request->getStr('recaptcha_challenge_field');
39-
$response = $request->getStr('recaptcha_response_field');
40-
$resp = recaptcha_check_answer(
41-
PhabricatorEnv::getEnvConfig('recaptcha.private-key'),
42-
$_SERVER['REMOTE_ADDR'],
43-
$challenge,
44-
$response);
33+
list($body) = id(new HTTPSFuture($uri, $params))
34+
->setMethod('POST')
35+
->resolvex();
4536

46-
return (bool)@$resp->is_valid;
37+
$json = phutil_json_decode($body);
38+
return (bool)idx($json, 'success');
4739
}
4840

4941
protected function renderInput() {
50-
self::requireLib();
51-
52-
$uri = new PhutilURI(PhabricatorEnv::getEnvConfig('phabricator.base-uri'));
53-
$protocol = $uri->getProtocol();
54-
$use_ssl = ($protocol == 'https');
55-
56-
return phutil_safe_html(recaptcha_get_html(
57-
PhabricatorEnv::getEnvConfig('recaptcha.public-key'),
58-
$error = null,
59-
$use_ssl));
42+
$js = 'https://www.google.com/recaptcha/api.js';
43+
$pubkey = PhabricatorEnv::getEnvConfig('recaptcha.public-key');
44+
45+
return array(
46+
phutil_tag('div', array(
47+
'class' => 'g-recaptcha',
48+
'data-sitekey' => $pubkey,
49+
)),
50+
51+
phutil_tag('script', array(
52+
'type' => 'text/javascript',
53+
'src' => $js,
54+
)),
55+
);
6056
}
61-
6257
}

0 commit comments

Comments
 (0)
Failed to load comments.