1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +01:00

Improve handling of "Deny" responses from Duo

Summary:
Ref T13231. See <https://discourse.phabricator-community.org/t/duo-integration-crashes-if-user-is-not-enrolled-and-enrollment-is-disabled/2340/5>

(There's an actual bug here, although I'm not sure exactly what's going on on the Duo side in the report.)

Test Plan:
To reproduce this, I was only able to actually "Deny" my account explicitly in Duo.

  - With "Deny", tried to add a factor. Got a nice helpful error message.
  - Undenied, added a factor, re-denied, tried to pass an MFA gate. Got another nice helpful error message.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13231

Differential Revision: https://secure.phabricator.com/D20065
This commit is contained in:
epriestley 2019-01-29 20:45:18 -08:00
parent 93b512b63c
commit e9b2d667ee
2 changed files with 27 additions and 5 deletions

View file

@ -147,7 +147,7 @@ abstract class PhabricatorAuthFactor extends Phobject {
$viewer, $viewer,
$challenges); $challenges);
if ($new_challenges instanceof PhabricatorAuthFactorResult) { if ($this->isAuthResult($new_challenges)) {
unset($unguarded); unset($unguarded);
return $new_challenges; return $new_challenges;
} }
@ -200,7 +200,7 @@ abstract class PhabricatorAuthFactor extends Phobject {
return $result; return $result;
} }
if (!($result instanceof PhabricatorAuthFactorResult)) { if (!$this->isAuthResult($result)) {
throw new Exception( throw new Exception(
pht( pht(
'Expected "newResultFromIssuedChallenges()" to return null or '. 'Expected "newResultFromIssuedChallenges()" to return null or '.
@ -232,7 +232,7 @@ abstract class PhabricatorAuthFactor extends Phobject {
$request, $request,
$challenges); $challenges);
if (!($result instanceof PhabricatorAuthFactorResult)) { if (!$this->isAuthResult($result)) {
throw new Exception( throw new Exception(
pht( pht(
'Expected "newResultFromChallengeResponse()" to return an object '. 'Expected "newResultFromChallengeResponse()" to return an object '.
@ -408,6 +408,10 @@ abstract class PhabricatorAuthFactor extends Phobject {
$provider, $provider,
$user); $user);
if ($this->isAuthResult($properties)) {
return $properties;
}
foreach ($properties as $key => $value) { foreach ($properties as $key => $value) {
$sync_token->setTemporaryTokenProperty($key, $value); $sync_token->setTemporaryTokenProperty($key, $value);
} }
@ -555,4 +559,8 @@ abstract class PhabricatorAuthFactor extends Phobject {
->execute(); ->execute();
} }
final protected function isAuthResult($object) {
return ($object instanceof PhabricatorAuthFactorResult);
}
} }

View file

@ -157,6 +157,10 @@ final class PhabricatorDuoAuthFactor
PhabricatorUser $user) { PhabricatorUser $user) {
$token = $this->loadMFASyncToken($provider, $request, $form, $user); $token = $this->loadMFASyncToken($provider, $request, $form, $user);
if ($this->isAuthResult($token)) {
$form->appendChild($this->newAutomaticControl($token));
return;
}
$enroll = $token->getTemporaryTokenProperty('duo.enroll'); $enroll = $token->getTemporaryTokenProperty('duo.enroll');
$duo_id = $token->getTemporaryTokenProperty('duo.user-id'); $duo_id = $token->getTemporaryTokenProperty('duo.user-id');
@ -350,6 +354,7 @@ final class PhabricatorDuoAuthFactor
$external_uri = null; $external_uri = null;
$result_code = $result['response']['result']; $result_code = $result['response']['result'];
$status_message = $result['response']['status_msg'];
switch ($result_code) { switch ($result_code) {
case 'auth': case 'auth':
case 'allow': case 'allow':
@ -376,7 +381,13 @@ final class PhabricatorDuoAuthFactor
return $this->newResult() return $this->newResult()
->setIsError(true) ->setIsError(true)
->setErrorMessage( ->setErrorMessage(
pht('Your account is not permitted to access this system.')); pht(
'Your Duo account ("%s") is not permitted to access this '.
'system. Contact your Duo administrator for help. '.
'The Duo preauth API responded with status message ("%s"): %s',
$duo_user,
$result_code,
$status_message));
} }
// Duo's "/enroll" API isn't repeatable for the same username. If we're // Duo's "/enroll" API isn't repeatable for the same username. If we're
@ -476,7 +487,10 @@ final class PhabricatorDuoAuthFactor
->setIsError(true) ->setIsError(true)
->setErrorMessage( ->setErrorMessage(
pht( pht(
'Duo has denied you access. Duo status message ("%s"): %s', 'Your Duo account ("%s") is not permitted to access this '.
'system. Contact your Duo administrator for help. The Duo '.
'preauth API responded with status message ("%s"): %s',
$duo_user,
$next_step, $next_step,
$status_message)); $status_message));
} }