Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/factor/PhabricatorAuthFactor.php
| Show First 20 Lines • Show All 226 Lines • ▼ Show 20 Lines | abstract protected function newResultFromChallengeResponse( | ||||
| PhabricatorAuthFactorConfig $config, | PhabricatorAuthFactorConfig $config, | ||||
| PhabricatorUser $viewer, | PhabricatorUser $viewer, | ||||
| AphrontRequest $request, | AphrontRequest $request, | ||||
| array $challenges); | array $challenges); | ||||
| final protected function newAutomaticControl( | final protected function newAutomaticControl( | ||||
| PhabricatorAuthFactorResult $result) { | PhabricatorAuthFactorResult $result) { | ||||
| $is_error = $result->getIsError(); | |||||
| if ($is_error) { | |||||
| return $this->newErrorControl($result); | |||||
| } | |||||
epriestley: For hard error results, like "ur duo is v. broken". | |||||
| $is_continue = $result->getIsContinue(); | |||||
| if ($is_continue) { | |||||
| return $this->newContinueControl($result); | |||||
| } | |||||
| $is_answered = (bool)$result->getAnsweredChallenge(); | $is_answered = (bool)$result->getAnsweredChallenge(); | ||||
| if ($is_answered) { | if ($is_answered) { | ||||
| return $this->newAnsweredControl($result); | return $this->newAnsweredControl($result); | ||||
| } | } | ||||
| $is_wait = $result->getIsWait(); | $is_wait = $result->getIsWait(); | ||||
| if ($is_wait) { | if ($is_wait) { | ||||
| return $this->newWaitControl($result); | return $this->newWaitControl($result); | ||||
| Show All 23 Lines | $icon = id(new PHUIIconView()) | ||||
| ->setIcon('fa-check-circle-o', 'green'); | ->setIcon('fa-check-circle-o', 'green'); | ||||
| return id(new PHUIFormTimerControl()) | return id(new PHUIFormTimerControl()) | ||||
| ->setIcon($icon) | ->setIcon($icon) | ||||
| ->appendChild( | ->appendChild( | ||||
| pht('You responded to this challenge correctly.')); | pht('You responded to this challenge correctly.')); | ||||
| } | } | ||||
| private function newErrorControl( | |||||
| PhabricatorAuthFactorResult $result) { | |||||
| $error = $result->getErrorMessage(); | |||||
| $icon = id(new PHUIIconView()) | |||||
| ->setIcon('fa-times', 'red'); | |||||
| return id(new PHUIFormTimerControl()) | |||||
| ->setIcon($icon) | |||||
| ->appendChild($error) | |||||
| ->setError(pht('Error')); | |||||
| } | |||||
| private function newContinueControl( | |||||
| PhabricatorAuthFactorResult $result) { | |||||
| $error = $result->getErrorMessage(); | |||||
| $icon = id(new PHUIIconView()) | |||||
| ->setIcon('fa-commenting', 'green'); | |||||
| return id(new PHUIFormTimerControl()) | |||||
| ->setIcon($icon) | |||||
| ->appendChild($error); | |||||
| } | |||||
| /* -( Synchronizing New Factors )------------------------------------------ */ | /* -( Synchronizing New Factors )------------------------------------------ */ | ||||
| final protected function loadMFASyncToken( | final protected function loadMFASyncToken( | ||||
| AphrontRequest $request, | AphrontRequest $request, | ||||
| AphrontFormView $form, | AphrontFormView $form, | ||||
| PhabricatorUser $user) { | PhabricatorUser $user) { | ||||
| ▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | foreach ($challenges as $challenge) { | ||||
| } | } | ||||
| return $challenge; | return $challenge; | ||||
| } | } | ||||
| return null; | return null; | ||||
| } | } | ||||
| /** | |||||
| * @phutil-external-symbol class QRcode | |||||
| */ | |||||
| final protected function newQRCode($uri) { | |||||
Done Inline ActionsDuo needs QR so I lifted this up to the base class. epriestley: Duo needs QR so I lifted this up to the base class. | |||||
| $root = dirname(phutil_get_library_root('phabricator')); | |||||
| require_once $root.'/externals/phpqrcode/phpqrcode.php'; | |||||
| $lines = QRcode::text($uri); | |||||
| $total_width = 240; | |||||
| $cell_size = floor($total_width / count($lines)); | |||||
| $rows = array(); | |||||
| foreach ($lines as $line) { | |||||
| $cells = array(); | |||||
| for ($ii = 0; $ii < strlen($line); $ii++) { | |||||
| if ($line[$ii] == '1') { | |||||
| $color = '#000'; | |||||
| } else { | |||||
| $color = '#fff'; | |||||
| } | |||||
| $cells[] = phutil_tag( | |||||
| 'td', | |||||
| array( | |||||
| 'width' => $cell_size, | |||||
| 'height' => $cell_size, | |||||
| 'style' => 'background: '.$color, | |||||
| ), | |||||
| ''); | |||||
| } | |||||
| $rows[] = phutil_tag('tr', array(), $cells); | |||||
| } | |||||
Not Done Inline ActionsI think it's kind of hilarious that we use phpqrcode to generate the bitmap and then use a huge <table> element to render it. amckinley: I think it's kind of hilarious that we use `phpqrcode` to generate the bitmap and then use a… | |||||
Done Inline ActionsOn the one hand this is completely ridicluous, but it doesn't require gd, doesn't have issues with data: URI length, doesn't require a separate <img /> request or a QR endpoint, scales well to different resolutions... And a QR code is likely never going to have so much data that this completely fails, since phones still have to be able to resolve them with the camera. epriestley: On the one hand this is completely ridicluous, but it doesn't require `gd`, doesn't have issues… | |||||
| return phutil_tag( | |||||
| 'table', | |||||
| array( | |||||
| 'style' => 'margin: 24px auto;', | |||||
| ), | |||||
| $rows); | |||||
| } | |||||
| final protected function throwResult(PhabricatorAuthFactorResult $result) { | |||||
| throw new PhabricatorAuthFactorResultException($result); | |||||
| } | |||||
| final protected function getInstallDisplayName() { | |||||
Done Inline ActionsBoth Duo and SMS use this. epriestley: Both Duo and SMS use this. | |||||
| $uri = PhabricatorEnv::getURI('/'); | |||||
| $uri = new PhutilURI($uri); | |||||
| return $uri->getDomain(); | |||||
| } | |||||
| final protected function getChallengeResponseParameterName( | |||||
| PhabricatorAuthFactorConfig $config) { | |||||
| return $this->getParameterName($config, 'mfa.response'); | |||||
| } | |||||
| final protected function getChallengeResponseFromRequest( | |||||
| PhabricatorAuthFactorConfig $config, | |||||
| AphrontRequest $request) { | |||||
| $name = $this->getChallengeResponseParameterName($config); | |||||
| $value = $request->getStr($name); | |||||
| $value = (string)$value; | |||||
| $value = trim($value); | |||||
| return $value; | |||||
| } | |||||
Done Inline ActionsEverything that requires you to type something can share this stuff. epriestley: Everything that requires you to type something can share this stuff. | |||||
| final protected function hasCSRF(PhabricatorAuthFactorConfig $config) { | |||||
| $engine = $config->getSessionEngine(); | |||||
| $request = $engine->getRequest(); | |||||
| if (!$request->isHTTPPost()) { | |||||
| return false; | |||||
| } | |||||
| return $request->validateCSRF(); | |||||
| } | |||||
| } | } | ||||
For hard error results, like "ur duo is v. broken".