Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/engine/PhabricatorAuthSessionEngine.php
Show First 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | public function requireHighSecuritySession( | ||||
if (!$viewer->hasSession()) { | if (!$viewer->hasSession()) { | ||||
throw new Exception( | throw new Exception( | ||||
pht('Requiring a high-security session from a user with no session!')); | pht('Requiring a high-security session from a user with no session!')); | ||||
} | } | ||||
$session = $viewer->getSession(); | $session = $viewer->getSession(); | ||||
// Check if the session is already in high security mode. | |||||
$token = $this->issueHighSecurityToken($session); | $token = $this->issueHighSecurityToken($session); | ||||
if ($token) { | if ($token) { | ||||
return $token; | return $token; | ||||
} | } | ||||
// Load the multi-factor auth sources attached to this account. | |||||
$factors = id(new PhabricatorAuthFactorConfig())->loadAllWhere( | |||||
'userPHID = %s', | |||||
$viewer->getPHID()); | |||||
// If the account has no associated multi-factor auth, just issue a token | |||||
// without putting the session into high security mode. This is generally | |||||
// easier for users. A minor but desirable side effect is that when a user | |||||
// adds an auth factor, existing sessions won't get a free pass into hisec, | |||||
// since they never actually got marked as hisec. | |||||
if (!$factors) { | |||||
return $this->issueHighSecurityToken($session, true); | |||||
} | |||||
$validation_results = array(); | |||||
if ($request->isHTTPPost()) { | if ($request->isHTTPPost()) { | ||||
$request->validateCSRF(); | $request->validateCSRF(); | ||||
if ($request->getExists(AphrontRequest::TYPE_HISEC)) { | if ($request->getExists(AphrontRequest::TYPE_HISEC)) { | ||||
// TODO: Actually verify that the user provided some multi-factor | $ok = true; | ||||
// auth credentials here. For now, we just let you enter high | foreach ($factors as $factor) { | ||||
// security. | $id = $factor->getID(); | ||||
$impl = $factor->requireImplementation(); | |||||
$validation_results[$id] = $impl->processValidateFactorForm( | |||||
$factor, | |||||
$viewer, | |||||
$request); | |||||
if (!$impl->isFactorValid($factor, $validation_results[$id])) { | |||||
$ok = false; | |||||
} | |||||
} | |||||
if ($ok) { | |||||
$until = time() + phutil_units('15 minutes in seconds'); | $until = time() + phutil_units('15 minutes in seconds'); | ||||
$session->setHighSecurityUntil($until); | $session->setHighSecurityUntil($until); | ||||
queryfx( | queryfx( | ||||
$session->establishConnection('w'), | $session->establishConnection('w'), | ||||
'UPDATE %T SET highSecurityUntil = %d WHERE id = %d', | 'UPDATE %T SET highSecurityUntil = %d WHERE id = %d', | ||||
$session->getTableName(), | $session->getTableName(), | ||||
$until, | $until, | ||||
$session->getID()); | $session->getID()); | ||||
$log = PhabricatorUserLog::initializeNewLog( | $log = PhabricatorUserLog::initializeNewLog( | ||||
$viewer, | $viewer, | ||||
$viewer->getPHID(), | $viewer->getPHID(), | ||||
PhabricatorUserLog::ACTION_ENTER_HISEC); | PhabricatorUserLog::ACTION_ENTER_HISEC); | ||||
$log->save(); | $log->save(); | ||||
} else { | |||||
$log = PhabricatorUserLog::initializeNewLog( | |||||
$viewer, | |||||
$viewer->getPHID(), | |||||
PhabricatorUserLog::ACTION_FAIL_HISEC); | |||||
$log->save(); | |||||
} | |||||
} | } | ||||
} | } | ||||
$token = $this->issueHighSecurityToken($session); | $token = $this->issueHighSecurityToken($session); | ||||
if ($token) { | if ($token) { | ||||
return $token; | return $token; | ||||
} | } | ||||
throw id(new PhabricatorAuthHighSecurityRequiredException()) | throw id(new PhabricatorAuthHighSecurityRequiredException()) | ||||
->setCancelURI($cancel_uri); | ->setCancelURI($cancel_uri) | ||||
->setFactors($factors) | |||||
->setFactorValidationResults($validation_results); | |||||
} | } | ||||
/** | /** | ||||
* Issue a high security token for a session, if authorized. | * Issue a high security token for a session, if authorized. | ||||
* | * | ||||
* @param PhabricatorAuthSession Session to issue a token for. | * @param PhabricatorAuthSession Session to issue a token for. | ||||
* @return PhabricatorAuthHighSecurityToken|null Token, if authorized. | * @return PhabricatorAuthHighSecurityToken|null Token, if authorized. | ||||
Show All 10 Lines | final class PhabricatorAuthSessionEngine extends Phobject { | ||||
/** | /** | ||||
* Render a form for providing relevant multi-factor credentials. | * Render a form for providing relevant multi-factor credentials. | ||||
* | * | ||||
* @param PhabricatorUser Viewing user. | * @param PhabricatorUser Viewing user. | ||||
* @param AphrontRequest Current request. | * @param AphrontRequest Current request. | ||||
* @return AphrontFormView Renderable form. | * @return AphrontFormView Renderable form. | ||||
*/ | */ | ||||
public function renderHighSecurityForm( | public function renderHighSecurityForm( | ||||
array $factors, | |||||
array $validation_results, | |||||
PhabricatorUser $viewer, | PhabricatorUser $viewer, | ||||
AphrontRequest $request) { | AphrontRequest $request) { | ||||
// TODO: This is stubbed. | |||||
$form = id(new AphrontFormView()) | $form = id(new AphrontFormView()) | ||||
->setUser($viewer) | ->setUser($viewer) | ||||
->appendRemarkupInstructions('') | |||||
->appendChild( | |||||
id(new AphrontFormTextControl()) | |||||
->setLabel(pht('Secret Stuff'))) | |||||
->appendRemarkupInstructions(''); | ->appendRemarkupInstructions(''); | ||||
foreach ($factors as $factor) { | |||||
$factor->requireImplementation()->renderValidateFactorForm( | |||||
$factor, | |||||
$form, | |||||
$viewer, | |||||
idx($validation_results, $factor->getID())); | |||||
} | |||||
$form->appendRemarkupInstructions(''); | |||||
return $form; | return $form; | ||||
} | } | ||||
public function exitHighSecurity( | public function exitHighSecurity( | ||||
PhabricatorUser $viewer, | PhabricatorUser $viewer, | ||||
PhabricatorAuthSession $session) { | PhabricatorAuthSession $session) { | ||||
Show All 14 Lines |