mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Replace old rate limiting in password login flow with "SystemAction" rate limiting
Summary: Depends on D20667. Ref T13343. Password auth currently uses an older rate limiting mechanism, upgrade it to the modern "SystemAction" mechanism. This mostly just improves consistency, although there are some tangential/theoretical benefits: - it's not obvious that making the user log GC very quickly could disable rate limiting; - if we let you configure action limits in the future, which we might, this would become configurable for free. Test Plan: - With CAPTCHAs off, made a bunch of invalid login attempts. Got rate limited. - With CAPTCHAs on, made a bunch of invalid login attempts. Got downgraded to CAPTCHAs after a few. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13343 Differential Revision: https://secure.phabricator.com/D20668
This commit is contained in:
parent
e090b32c75
commit
a75766c0e5
4 changed files with 53 additions and 30 deletions
|
@ -2431,6 +2431,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthTestSMSAction' => 'applications/auth/action/PhabricatorAuthTestSMSAction.php',
|
||||
'PhabricatorAuthTryEmailLoginAction' => 'applications/auth/action/PhabricatorAuthTryEmailLoginAction.php',
|
||||
'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php',
|
||||
'PhabricatorAuthTryPasswordAction' => 'applications/auth/action/PhabricatorAuthTryPasswordAction.php',
|
||||
'PhabricatorAuthTryPasswordWithoutCAPTCHAAction' => 'applications/auth/action/PhabricatorAuthTryPasswordWithoutCAPTCHAAction.php',
|
||||
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
|
||||
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
|
||||
'PhabricatorAuthWaitForApprovalMessageType' => 'applications/auth/message/PhabricatorAuthWaitForApprovalMessageType.php',
|
||||
|
@ -8427,6 +8429,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthTestSMSAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryEmailLoginAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryPasswordAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthTryPasswordWithoutCAPTCHAAction' => 'PhabricatorSystemAction',
|
||||
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthWaitForApprovalMessageType' => 'PhabricatorAuthMessageType',
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthTryPasswordAction
|
||||
extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'auth.password';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 100 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
public function getLimitExplanation() {
|
||||
return pht(
|
||||
'Your remote address has made too many login attempts in a short '.
|
||||
'period of time.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthTryPasswordWithoutCAPTCHAAction
|
||||
extends PhabricatorSystemAction {
|
||||
|
||||
const TYPECONST = 'auth.password-without-captcha';
|
||||
|
||||
public function getActionConstant() {
|
||||
return self::TYPECONST;
|
||||
}
|
||||
|
||||
public function getScoreThreshold() {
|
||||
return 10 / phutil_units('1 hour in seconds');
|
||||
}
|
||||
|
||||
}
|
|
@ -255,48 +255,29 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
|
|||
$viewer = $request->getUser();
|
||||
$content_source = PhabricatorContentSource::newFromRequest($request);
|
||||
|
||||
$captcha_limit = 5;
|
||||
$hard_limit = 32;
|
||||
$limit_window = phutil_units('15 minutes in seconds');
|
||||
$rate_actor = PhabricatorSystemActionEngine::newActorFromRequest($request);
|
||||
|
||||
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
|
||||
PhabricatorUserLog::ACTION_LOGIN_FAILURE,
|
||||
$limit_window);
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($rate_actor),
|
||||
new PhabricatorAuthTryPasswordAction(),
|
||||
1);
|
||||
|
||||
// If the same remote address has submitted several failed login attempts
|
||||
// recently, require they provide a CAPTCHA response for new attempts.
|
||||
$require_captcha = false;
|
||||
$captcha_valid = false;
|
||||
if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) {
|
||||
if (count($failed_attempts) > $captcha_limit) {
|
||||
try {
|
||||
PhabricatorSystemActionEngine::willTakeAction(
|
||||
array($rate_actor),
|
||||
new PhabricatorAuthTryPasswordWithoutCAPTCHAAction(),
|
||||
1);
|
||||
} catch (PhabricatorSystemActionRateLimitException $ex) {
|
||||
$require_captcha = true;
|
||||
$captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request);
|
||||
}
|
||||
}
|
||||
|
||||
// If the user has submitted quite a few failed login attempts recently,
|
||||
// give them a hard limit.
|
||||
if (count($failed_attempts) > $hard_limit) {
|
||||
$guidance = array();
|
||||
|
||||
$guidance[] = pht(
|
||||
'Your remote address has failed too many login attempts recently. '.
|
||||
'Wait a few minutes before trying again.');
|
||||
|
||||
$guidance[] = pht(
|
||||
'If you are unable to log in to your account, you can '.
|
||||
'[[ /login/email | send a reset link to your email address ]].');
|
||||
|
||||
$guidance = implode("\n\n", $guidance);
|
||||
|
||||
$dialog = $controller->newDialog()
|
||||
->setTitle(pht('Too Many Login Attempts'))
|
||||
->appendChild(new PHUIRemarkupView($viewer, $guidance))
|
||||
->addCancelButton('/auth/start/', pht('Wait Patiently'));
|
||||
|
||||
return array(null, $dialog);
|
||||
}
|
||||
|
||||
$response = null;
|
||||
$account = null;
|
||||
$log_user = null;
|
||||
|
|
Loading…
Reference in a new issue