mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-14 16:51:08 +01:00
Require multiple auth factors to establish web sessions
Summary: Ref T4398. This prompts users for multi-factor auth on login. Roughly, this introduces the idea of "partial" sessions, which we haven't finished constructing yet. In practice, this means the session has made it through primary auth but not through multi-factor auth. Add a workflow for bringing a partial session up to a full one. Test Plan: - Used Conduit. - Logged in as multi-factor user. - Logged in as no-factor user. - Tried to do non-login-things with a partial session. - Reviewed account activity logs. {F149295} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T4398 Differential Revision: https://secure.phabricator.com/D8922
This commit is contained in:
parent
1e6b2f26e9
commit
50376aad04
15 changed files with 190 additions and 27 deletions
2
resources/sql/autopatches/20140430.auth.1.partial.sql
Normal file
2
resources/sql/autopatches/20140430.auth.1.partial.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_user.phabricator_session
|
||||||
|
ADD isPartial BOOL NOT NULL DEFAULT 0;
|
|
@ -1213,6 +1213,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php',
|
'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php',
|
||||||
'PhabricatorAuthFactorTOTP' => 'applications/auth/factor/PhabricatorAuthFactorTOTP.php',
|
'PhabricatorAuthFactorTOTP' => 'applications/auth/factor/PhabricatorAuthFactorTOTP.php',
|
||||||
'PhabricatorAuthFactorTOTPTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTOTPTestCase.php',
|
'PhabricatorAuthFactorTOTPTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTOTPTestCase.php',
|
||||||
|
'PhabricatorAuthFinishController' => 'applications/auth/controller/PhabricatorAuthFinishController.php',
|
||||||
'PhabricatorAuthHighSecurityRequiredException' => 'applications/auth/exception/PhabricatorAuthHighSecurityRequiredException.php',
|
'PhabricatorAuthHighSecurityRequiredException' => 'applications/auth/exception/PhabricatorAuthHighSecurityRequiredException.php',
|
||||||
'PhabricatorAuthHighSecurityToken' => 'applications/auth/data/PhabricatorAuthHighSecurityToken.php',
|
'PhabricatorAuthHighSecurityToken' => 'applications/auth/data/PhabricatorAuthHighSecurityToken.php',
|
||||||
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
|
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
|
||||||
|
@ -3980,6 +3981,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthFactorConfig' => 'PhabricatorAuthDAO',
|
'PhabricatorAuthFactorConfig' => 'PhabricatorAuthDAO',
|
||||||
'PhabricatorAuthFactorTOTP' => 'PhabricatorAuthFactor',
|
'PhabricatorAuthFactorTOTP' => 'PhabricatorAuthFactor',
|
||||||
'PhabricatorAuthFactorTOTPTestCase' => 'PhabricatorTestCase',
|
'PhabricatorAuthFactorTOTPTestCase' => 'PhabricatorTestCase',
|
||||||
|
'PhabricatorAuthFinishController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthHighSecurityRequiredException' => 'Exception',
|
'PhabricatorAuthHighSecurityRequiredException' => 'Exception',
|
||||||
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
|
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
|
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
|
||||||
|
|
|
@ -16,6 +16,10 @@ final class DarkConsoleController extends PhabricatorController {
|
||||||
return !PhabricatorEnv::getEnvConfig('darkconsole.always-on');
|
return !PhabricatorEnv::getEnvConfig('darkconsole.always-on');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
|
@ -15,6 +15,10 @@ final class DarkConsoleDataController extends PhabricatorController {
|
||||||
return !PhabricatorEnv::getEnvConfig('darkconsole.always-on');
|
return !PhabricatorEnv::getEnvConfig('darkconsole.always-on');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function willProcessRequest(array $data) {
|
||||||
$this->key = $data['key'];
|
$this->key = $data['key'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ final class PhabricatorApplicationAuth extends PhabricatorApplication {
|
||||||
'register/(?:(?P<akey>[^/]+)/)?' => 'PhabricatorAuthRegisterController',
|
'register/(?:(?P<akey>[^/]+)/)?' => 'PhabricatorAuthRegisterController',
|
||||||
'start/' => 'PhabricatorAuthStartController',
|
'start/' => 'PhabricatorAuthStartController',
|
||||||
'validate/' => 'PhabricatorAuthValidateController',
|
'validate/' => 'PhabricatorAuthValidateController',
|
||||||
|
'finish/' => 'PhabricatorAuthFinishController',
|
||||||
'unlink/(?P<pkey>[^/]+)/' => 'PhabricatorAuthUnlinkController',
|
'unlink/(?P<pkey>[^/]+)/' => 'PhabricatorAuthUnlinkController',
|
||||||
'(?P<action>link|refresh)/(?P<pkey>[^/]+)/'
|
'(?P<action>link|refresh)/(?P<pkey>[^/]+)/'
|
||||||
=> 'PhabricatorAuthLinkController',
|
=> 'PhabricatorAuthLinkController',
|
||||||
|
|
|
@ -82,7 +82,7 @@ abstract class PhabricatorAuthController extends PhabricatorController {
|
||||||
$should_login = $event->getValue('shouldLogin');
|
$should_login = $event->getValue('shouldLogin');
|
||||||
if ($should_login) {
|
if ($should_login) {
|
||||||
$session_key = id(new PhabricatorAuthSessionEngine())
|
$session_key = id(new PhabricatorAuthSessionEngine())
|
||||||
->establishSession($session_type, $user->getPHID());
|
->establishSession($session_type, $user->getPHID(), $partial = true);
|
||||||
|
|
||||||
// NOTE: We allow disabled users to login and roadblock them later, so
|
// NOTE: We allow disabled users to login and roadblock them later, so
|
||||||
// there's no check for users being disabled here.
|
// there's no check for users being disabled here.
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorAuthFinishController
|
||||||
|
extends PhabricatorAuthController {
|
||||||
|
|
||||||
|
public function shouldRequireLogin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
// If the user already has a full session, just kick them out of here.
|
||||||
|
$has_partial_session = $viewer->hasSession() &&
|
||||||
|
$viewer->getSession()->getIsPartial();
|
||||||
|
if (!$has_partial_session) {
|
||||||
|
return id(new AphrontRedirectResponse())->setURI('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$engine = new PhabricatorAuthSessionEngine();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$token = $engine->requireHighSecuritySession(
|
||||||
|
$viewer,
|
||||||
|
$request,
|
||||||
|
'/logout/');
|
||||||
|
} catch (PhabricatorAuthHighSecurityRequiredException $ex) {
|
||||||
|
$form = id(new PhabricatorAuthSessionEngine())->renderHighSecurityForm(
|
||||||
|
$ex->getFactors(),
|
||||||
|
$ex->getFactorValidationResults(),
|
||||||
|
$viewer,
|
||||||
|
$request);
|
||||||
|
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Provide Multi-Factor Credentials'))
|
||||||
|
->setShortTitle(pht('Multi-Factor Login'))
|
||||||
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->addHiddenInput(AphrontRequest::TYPE_HISEC, true)
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'Welcome, %s. To complete the login process, provide your '.
|
||||||
|
'multi-factor credentials.',
|
||||||
|
phutil_tag('strong', array(), $viewer->getUsername())))
|
||||||
|
->appendChild($form->buildLayoutView())
|
||||||
|
->setSubmitURI($request->getPath())
|
||||||
|
->addCancelButton($ex->getCancelURI())
|
||||||
|
->addSubmitButton(pht('Continue'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upgrade the partial session to a full session.
|
||||||
|
$engine->upgradePartialSession($viewer);
|
||||||
|
|
||||||
|
// TODO: It might be nice to add options like "bind this session to my IP"
|
||||||
|
// here, even for accounts without multi-factor auth attached to them.
|
||||||
|
|
||||||
|
$next = PhabricatorCookies::getNextURICookie($request);
|
||||||
|
$request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI);
|
||||||
|
|
||||||
|
if (!PhabricatorEnv::isValidLocalWebResource($next)) {
|
||||||
|
$next = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($next);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,10 @@ final class PhabricatorAuthValidateController
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$viewer = $request->getUser();
|
$viewer = $request->getUser();
|
||||||
|
@ -54,14 +58,8 @@ final class PhabricatorAuthValidateController
|
||||||
return $this->renderErrors($failures);
|
return $this->renderErrors($failures);
|
||||||
}
|
}
|
||||||
|
|
||||||
$next = PhabricatorCookies::getNextURICookie($request);
|
$finish_uri = $this->getApplicationURI('finish/');
|
||||||
$request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI);
|
return id(new AphrontRedirectResponse())->setURI($finish_uri);
|
||||||
|
|
||||||
if (!PhabricatorEnv::isValidLocalWebResource($next)) {
|
|
||||||
$next = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderErrors(array $messages) {
|
private function renderErrors(array $messages) {
|
||||||
|
|
|
@ -17,6 +17,10 @@ final class PhabricatorLogoutController
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
|
@ -94,6 +94,7 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
s.sessionExpires AS s_sessionExpires,
|
s.sessionExpires AS s_sessionExpires,
|
||||||
s.sessionStart AS s_sessionStart,
|
s.sessionStart AS s_sessionStart,
|
||||||
s.highSecurityUntil AS s_highSecurityUntil,
|
s.highSecurityUntil AS s_highSecurityUntil,
|
||||||
|
s.isPartial AS s_isPartial,
|
||||||
u.*
|
u.*
|
||||||
FROM %T u JOIN %T s ON u.phid = s.userPHID
|
FROM %T u JOIN %T s ON u.phid = s.userPHID
|
||||||
AND s.type = %s AND s.sessionKey = %s',
|
AND s.type = %s AND s.sessionKey = %s',
|
||||||
|
@ -159,9 +160,10 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
* @{class:PhabricatorAuthSession}).
|
* @{class:PhabricatorAuthSession}).
|
||||||
* @param phid|null Identity to establish a session for, usually a user
|
* @param phid|null Identity to establish a session for, usually a user
|
||||||
* PHID. With `null`, generates an anonymous session.
|
* PHID. With `null`, generates an anonymous session.
|
||||||
|
* @param bool True to issue a partial session.
|
||||||
* @return string Newly generated session key.
|
* @return string Newly generated session key.
|
||||||
*/
|
*/
|
||||||
public function establishSession($session_type, $identity_phid) {
|
public function establishSession($session_type, $identity_phid, $partial) {
|
||||||
// Consume entropy to generate a new session key, forestalling the eventual
|
// Consume entropy to generate a new session key, forestalling the eventual
|
||||||
// heat death of the universe.
|
// heat death of the universe.
|
||||||
$session_key = Filesystem::readRandomCharacters(40);
|
$session_key = Filesystem::readRandomCharacters(40);
|
||||||
|
@ -176,26 +178,32 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
// This has a side effect of validating the session type.
|
// This has a side effect of validating the session type.
|
||||||
$session_ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
|
$session_ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
|
||||||
|
|
||||||
|
$digest_key = PhabricatorHash::digest($session_key);
|
||||||
|
|
||||||
// Logging-in users don't have CSRF stuff yet, so we have to unguard this
|
// Logging-in users don't have CSRF stuff yet, so we have to unguard this
|
||||||
// write.
|
// write.
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
id(new PhabricatorAuthSession())
|
id(new PhabricatorAuthSession())
|
||||||
->setUserPHID($identity_phid)
|
->setUserPHID($identity_phid)
|
||||||
->setType($session_type)
|
->setType($session_type)
|
||||||
->setSessionKey(PhabricatorHash::digest($session_key))
|
->setSessionKey($digest_key)
|
||||||
->setSessionStart(time())
|
->setSessionStart(time())
|
||||||
->setSessionExpires(time() + $session_ttl)
|
->setSessionExpires(time() + $session_ttl)
|
||||||
|
->setIsPartial($partial ? 1 : 0)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$log = PhabricatorUserLog::initializeNewLog(
|
$log = PhabricatorUserLog::initializeNewLog(
|
||||||
null,
|
null,
|
||||||
$identity_phid,
|
$identity_phid,
|
||||||
PhabricatorUserLog::ACTION_LOGIN);
|
($partial
|
||||||
|
? PhabricatorUserLog::ACTION_LOGIN_PARTIAL
|
||||||
|
: PhabricatorUserLog::ACTION_LOGIN));
|
||||||
|
|
||||||
$log->setDetails(
|
$log->setDetails(
|
||||||
array(
|
array(
|
||||||
'session_type' => $session_type,
|
'session_type' => $session_type,
|
||||||
));
|
));
|
||||||
$log->setSession($session_key);
|
$log->setSession($digest_key);
|
||||||
$log->save();
|
$log->save();
|
||||||
unset($unguarded);
|
unset($unguarded);
|
||||||
|
|
||||||
|
@ -287,6 +295,12 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
new PhabricatorAuthTryFactorAction(),
|
new PhabricatorAuthTryFactorAction(),
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
|
if ($session->getIsPartial()) {
|
||||||
|
// If we have a partial session, just issue a token without
|
||||||
|
// putting it in high security mode.
|
||||||
|
return $this->issueHighSecurityToken($session, true);
|
||||||
|
}
|
||||||
|
|
||||||
$until = time() + phutil_units('15 minutes in seconds');
|
$until = time() + phutil_units('15 minutes in seconds');
|
||||||
$session->setHighSecurityUntil($until);
|
$session->setHighSecurityUntil($until);
|
||||||
|
|
||||||
|
@ -303,9 +317,6 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
PhabricatorUserLog::ACTION_ENTER_HISEC);
|
PhabricatorUserLog::ACTION_ENTER_HISEC);
|
||||||
$log->save();
|
$log->save();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$log = PhabricatorUserLog::initializeNewLog(
|
$log = PhabricatorUserLog::initializeNewLog(
|
||||||
$viewer,
|
$viewer,
|
||||||
$viewer->getPHID(),
|
$viewer->getPHID(),
|
||||||
|
@ -331,11 +342,15 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
* 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.
|
||||||
|
* @param bool Force token issue.
|
||||||
* @return PhabricatorAuthHighSecurityToken|null Token, if authorized.
|
* @return PhabricatorAuthHighSecurityToken|null Token, if authorized.
|
||||||
*/
|
*/
|
||||||
private function issueHighSecurityToken(PhabricatorAuthSession $session) {
|
private function issueHighSecurityToken(
|
||||||
|
PhabricatorAuthSession $session,
|
||||||
|
$force = false) {
|
||||||
|
|
||||||
$until = $session->getHighSecurityUntil();
|
$until = $session->getHighSecurityUntil();
|
||||||
if ($until > time()) {
|
if ($until > time() || $force) {
|
||||||
return new PhabricatorAuthHighSecurityToken();
|
return new PhabricatorAuthHighSecurityToken();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -390,4 +405,42 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
$log->save();
|
$log->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrade a partial session to a full session.
|
||||||
|
*
|
||||||
|
* @param PhabricatorAuthSession Session to upgrade.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function upgradePartialSession(PhabricatorUser $viewer) {
|
||||||
|
if (!$viewer->hasSession()) {
|
||||||
|
throw new Exception(
|
||||||
|
pht('Upgrading partial session of user with no session!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$session = $viewer->getSession();
|
||||||
|
|
||||||
|
if (!$session->getIsPartial()) {
|
||||||
|
throw new Exception(pht('Session is not partial!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
$session->setIsPartial(0);
|
||||||
|
|
||||||
|
queryfx(
|
||||||
|
$session->establishConnection('w'),
|
||||||
|
'UPDATE %T SET isPartial = %d WHERE id = %d',
|
||||||
|
$session->getTableName(),
|
||||||
|
0,
|
||||||
|
$session->getID());
|
||||||
|
|
||||||
|
$log = PhabricatorUserLog::initializeNewLog(
|
||||||
|
$viewer,
|
||||||
|
$viewer->getPHID(),
|
||||||
|
PhabricatorUserLog::ACTION_LOGIN_FULL);
|
||||||
|
$log->save();
|
||||||
|
unset($unguarded);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ final class PhabricatorAuthSession extends PhabricatorAuthDAO
|
||||||
protected $sessionStart;
|
protected $sessionStart;
|
||||||
protected $sessionExpires;
|
protected $sessionExpires;
|
||||||
protected $highSecurityUntil;
|
protected $highSecurityUntil;
|
||||||
|
protected $isPartial;
|
||||||
|
|
||||||
private $identityObject = self::ATTACHABLE;
|
private $identityObject = self::ATTACHABLE;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@ abstract class PhabricatorController extends AphrontController {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function shouldRequireEmailVerification() {
|
public function shouldRequireEmailVerification() {
|
||||||
return PhabricatorUserEmail::isEmailVerificationRequired();
|
return PhabricatorUserEmail::isEmailVerificationRequired();
|
||||||
}
|
}
|
||||||
|
@ -53,7 +57,8 @@ abstract class PhabricatorController extends AphrontController {
|
||||||
// session. This is used to provide CSRF protection to logged-out users.
|
// session. This is used to provide CSRF protection to logged-out users.
|
||||||
$phsid = $session_engine->establishSession(
|
$phsid = $session_engine->establishSession(
|
||||||
PhabricatorAuthSession::TYPE_WEB,
|
PhabricatorAuthSession::TYPE_WEB,
|
||||||
null);
|
null,
|
||||||
|
$partial = false);
|
||||||
|
|
||||||
// This may be a resource request, in which case we just don't set
|
// This may be a resource request, in which case we just don't set
|
||||||
// the cookie.
|
// the cookie.
|
||||||
|
@ -133,14 +138,24 @@ abstract class PhabricatorController extends AphrontController {
|
||||||
return $this->delegateToController($checker_controller);
|
return $this->delegateToController($checker_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$auth_class = 'PhabricatorApplicationAuth';
|
||||||
|
$auth_application = PhabricatorApplication::getByClass($auth_class);
|
||||||
|
|
||||||
|
// Require partial sessions to finish login before doing anything.
|
||||||
|
if (!$this->shouldAllowPartialSessions()) {
|
||||||
|
if ($user->hasSession() &&
|
||||||
|
$user->getSession()->getIsPartial()) {
|
||||||
|
$login_controller = new PhabricatorAuthFinishController($request);
|
||||||
|
$this->setCurrentApplication($auth_application);
|
||||||
|
return $this->delegateToController($login_controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->shouldRequireLogin()) {
|
if ($this->shouldRequireLogin()) {
|
||||||
// This actually means we need either:
|
// This actually means we need either:
|
||||||
// - a valid user, or a public controller; and
|
// - a valid user, or a public controller; and
|
||||||
// - permission to see the application.
|
// - permission to see the application.
|
||||||
|
|
||||||
$auth_class = 'PhabricatorApplicationAuth';
|
|
||||||
$auth_application = PhabricatorApplication::getByClass($auth_class);
|
|
||||||
|
|
||||||
$allow_public = $this->shouldAllowPublic() &&
|
$allow_public = $this->shouldAllowPublic() &&
|
||||||
PhabricatorEnv::getEnvConfig('policy.allow-public');
|
PhabricatorEnv::getEnvConfig('policy.allow-public');
|
||||||
|
|
||||||
|
|
|
@ -145,10 +145,10 @@ final class ConduitAPI_conduit_connect_Method extends ConduitAPIMethod {
|
||||||
if ($valid != $signature) {
|
if ($valid != $signature) {
|
||||||
throw new ConduitException('ERR-INVALID-CERTIFICATE');
|
throw new ConduitException('ERR-INVALID-CERTIFICATE');
|
||||||
}
|
}
|
||||||
$session_key = id(new PhabricatorAuthSessionEngine())
|
$session_key = id(new PhabricatorAuthSessionEngine())->establishSession(
|
||||||
->establishSession(
|
PhabricatorAuthSession::TYPE_CONDUIT,
|
||||||
PhabricatorAuthSession::TYPE_CONDUIT,
|
$user->getPHID(),
|
||||||
$user->getPHID());
|
$partial = false);
|
||||||
} else {
|
} else {
|
||||||
throw new ConduitException('ERR-NO-CERTIFICATE');
|
throw new ConduitException('ERR-NO-CERTIFICATE');
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||||
implements PhabricatorPolicyInterface {
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
const ACTION_LOGIN = 'login';
|
const ACTION_LOGIN = 'login';
|
||||||
|
const ACTION_LOGIN_PARTIAL = 'login-partial';
|
||||||
|
const ACTION_LOGIN_FULL = 'login-full';
|
||||||
const ACTION_LOGOUT = 'logout';
|
const ACTION_LOGOUT = 'logout';
|
||||||
const ACTION_LOGIN_FAILURE = 'login-fail';
|
const ACTION_LOGIN_FAILURE = 'login-fail';
|
||||||
const ACTION_RESET_PASSWORD = 'reset-pass';
|
const ACTION_RESET_PASSWORD = 'reset-pass';
|
||||||
|
@ -46,7 +48,9 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||||
public static function getActionTypeMap() {
|
public static function getActionTypeMap() {
|
||||||
return array(
|
return array(
|
||||||
self::ACTION_LOGIN => pht('Login'),
|
self::ACTION_LOGIN => pht('Login'),
|
||||||
self::ACTION_LOGIN_FAILURE => pht('Login Failure'),
|
self::ACTION_LOGIN_PARTIAL => pht('Login: Partial Login'),
|
||||||
|
self::ACTION_LOGIN_FULL => pht('Login: Upgrade to Full'),
|
||||||
|
self::ACTION_LOGIN_FAILURE => pht('Login: Failure'),
|
||||||
self::ACTION_LOGOUT => pht('Logout'),
|
self::ACTION_LOGOUT => pht('Logout'),
|
||||||
self::ACTION_RESET_PASSWORD => pht('Reset Password'),
|
self::ACTION_RESET_PASSWORD => pht('Reset Password'),
|
||||||
self::ACTION_CREATE => pht('Create Account'),
|
self::ACTION_CREATE => pht('Create Account'),
|
||||||
|
|
|
@ -14,6 +14,10 @@ abstract class CelerityResourceController extends PhabricatorController {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPartialSessions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
abstract public function getCelerityResourceMap();
|
abstract public function getCelerityResourceMap();
|
||||||
|
|
||||||
protected function serveResource($path, $package_hash = null) {
|
protected function serveResource($path, $package_hash = null) {
|
||||||
|
|
Loading…
Reference in a new issue