N°2311 - Refactor Login FSM Extensions

This commit is contained in:
Eric
2019-08-14 18:13:39 +02:00
parent 11f62063a6
commit 2ceb4068ad
9 changed files with 472 additions and 372 deletions

View File

@@ -30,7 +30,7 @@ require_once(APPROOT.'application/newsroomprovider.class.inc.php');
* @api
*/
interface iLoginFSMExtension
interface iLoginExtension
{
/**
* Return the list of supported login modes for this plugin
@@ -38,7 +38,10 @@ interface iLoginFSMExtension
* @return array of supported login modes
*/
public function ListSupportedLoginModes();
}
interface iLoginFSMExtension extends iLoginExtension
{
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
@@ -54,6 +57,128 @@ interface iLoginFSMExtension
public function LoginAction($sLoginState, &$iErrorCode);
}
abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
{
public abstract function ListSupportedLoginModes();
/**
* @inheritDoc
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState)
{
case LoginWebPage::LOGIN_STATE_START:
return $this->OnStart($iErrorCode);
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
return $this->OnModeDetection($iErrorCode);
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
return $this->OnReadCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
return $this->OnCheckCredentials($iErrorCode);
case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK:
return $this->OnCredentialsOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_USER_OK:
return $this->OnUsersOK($iErrorCode);
case LoginWebPage::LOGIN_STATE_CONNECTED:
return $this->OnConnected($iErrorCode);
case LoginWebPage::LOGIN_STATE_ERROR:
return $this->OnError($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Initialization
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
*/
protected function OnStart(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Detect login mode explicitly without respecting configured order (legacy mode)
* In most case do nothing here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
*/
protected function OnModeDetection(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Obtain the credentials either if login mode is empty or set to yours.
* This step can be called multiple times by the FSM:
* for example:
* 1 - display login form
* 2 - read the values posted by the user
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
*/
protected function OnReadCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Control the validity of the data provided by the user
* Automatic user provisioning can be done here
*
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
*/
protected function OnCheckCredentials(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCredentialsOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnUsersOK(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnError(&$iErrorCode)
{
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
}
interface iLogoutExtension extends iLoginExtension
{
/**
* Execute all actions to log out properly
*/
public function LogoutAction();
}
/**
* Implement this interface to change the behavior of the GUI for some objects.
*

View File

@@ -6,82 +6,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginBasic implements iLoginFSMExtension
class LoginBasic extends AbstractLoginFSMExtension
{
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_...
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState)
{
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
if (!isset($_SESSION['login_mode']))
{
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
{
$_SESSION['login_mode'] = 'basic';
}
elseif (isset($_SERVER['PHP_AUTH_USER']))
{
$_SESSION['login_mode'] = 'basic';
}
}
break;
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
if ($_SESSION['login_mode'] == 'basic')
{
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
break;
case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK:
if ($_SESSION['login_mode'] == 'basic')
{
list($sAuthUser) = $this->GetAuthUserAndPassword();
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
break;
case LoginWebPage::LOGIN_STATE_ERROR:
if ($_SESSION['login_mode'] == 'basic')
{
LoginWebPage::HTTP401Error();
}
break;
case LoginWebPage::LOGIN_STATE_CONNECTED:
if ($_SESSION['login_mode'] == 'basic')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
break;
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Return the list of supported login modes for this plugin
*
@@ -92,6 +18,65 @@ class LoginBasic implements iLoginFSMExtension
return array('basic');
}
protected function OnModeDetection(&$iErrorCode)
{
if (!isset($_SESSION['login_mode']))
{
if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
{
$_SESSION['login_mode'] = 'basic';
}
elseif (isset($_SERVER['PHP_AUTH_USER']))
{
$_SESSION['login_mode'] = 'basic';
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCheckCredentials(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'basic')
{
list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword();
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCredentialsOK(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'basic')
{
list($sAuthUser) = $this->GetAuthUserAndPassword();
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnError(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'basic')
{
LoginWebPage::HTTP401Error();
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'basic')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
private function GetAuthUserAndPassword()
{
$sAuthUser = '';

View File

@@ -1,65 +1,81 @@
<?php
/**
* Class LoginDefault
*
* @copyright Copyright (C) 2010-2019 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginDefault implements iLoginFSMExtension
/**
* Class LoginDefaultBefore
*/
class LoginDefaultBefore extends AbstractLoginFSMExtension
{
/**
* Return the list of supported login modes for this plugin
* Must be executed before the other login plugins
*
* @return array of supported login modes
*/
public function ListSupportedLoginModes()
{
return array('default');
return array('before');
}
protected function OnStart(&$iErrorCode)
{
// Check if proposed login mode is present and allowed
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
$sProposedLoginMode = utils::ReadParam('login_mode', '');
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
if ($index !== false)
{
// Force login mode
$_SESSION['login_mode'] = $sProposedLoginMode;
}
else
{
unset($_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnError(&$iErrorCode)
{
$_SESSION['login_error_count'] = (isset($_SESSION['login_error_count']) ? $_SESSION['login_error_count'] : 0) + 1;
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
unset($_SESSION['login_error_count']);
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
}
/**
* Class LoginDefaultAfter
*/
class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExtension
{
/**
* Must be executed after the other login plugins
*
* @return array of supported login modes
*/
public function ListSupportedLoginModes()
{
return array('after');
}
protected function OnError(&$iErrorCode)
{
unset($_SESSION['login_mode']);
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
* if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set
* if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated
* if LoginWebPage::LOGIN_FSM_RETURN_IGNORE is returned then the FSM will proceed to next plugin or state
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE
* Execute all actions to log out properly
*/
public function LoginAction($sLoginState, &$iErrorCode)
public function LogoutAction()
{
switch ($sLoginState)
{
case LoginWebPage::LOGIN_STATE_START:
// Check if proposed login mode is present and allowed
$aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
$sProposedLoginMode = utils::ReadParam('login_mode', '');
$index = array_search($sProposedLoginMode, $aAllowedLoginTypes);
if ($index !== false)
{
// Force login mode
$_SESSION['login_mode'] = $sProposedLoginMode;
}
else
{
unset($_SESSION['login_mode']);
}
break;
case LoginWebPage::LOGIN_STATE_ERROR:
$_SESSION['login_error_count'] = (isset($_SESSION['login_error_count']) ? $_SESSION['login_error_count'] : 0) + 1;
break;
case LoginWebPage::LOGIN_STATE_CONNECTED:
unset($_SESSION['login_error_count']);
break;
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
unset($_SESSION['login_mode']);
}
}

View File

@@ -7,7 +7,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginExternal implements iLoginFSMExtension
class LoginExternal extends AbstractLoginFSMExtension
{
/**
@@ -20,67 +20,50 @@ class LoginExternal implements iLoginFSMExtension
return array('external');
}
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_...
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function LoginAction($sLoginState, &$iErrorCode)
protected function OnModeDetection(&$iErrorCode)
{
switch ($sLoginState)
if (!isset($_SESSION['login_mode']))
{
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
if (!isset($_SESSION['login_mode']))
{
$sAuthUser = $this->GetAuthUser();
if ($sAuthUser && (strlen($sAuthUser) > 0))
{
$_SESSION['login_mode'] = 'external';
}
}
break;
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
if ($_SESSION['login_mode'] == 'external')
{
$sAuthUser = $this->GetAuthUser();
if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
break;
case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK:
if ($_SESSION['login_mode'] == 'external')
{
$sAuthUser = $this->GetAuthUser();
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
}
break;
case LoginWebPage::LOGIN_STATE_CONNECTED:
if ($_SESSION['login_mode'] == 'external')
{
$_SESSION['can_logoff'] = false;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
break;
$sAuthUser = $this->GetAuthUser();
if ($sAuthUser && (strlen($sAuthUser) > 0))
{
$_SESSION['login_mode'] = 'external';
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCheckCredentials(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'external')
{
$sAuthUser = $this->GetAuthUser();
if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCredentialsOK(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'external')
{
$sAuthUser = $this->GetAuthUser();
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'external')
{
$_SESSION['can_logoff'] = false;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}

View File

@@ -7,106 +7,10 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginForm implements iLoginFSMExtension
class LoginForm extends AbstractLoginFSMExtension
{
private $bForceFormOnError = false;
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_...
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState)
{
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd))
{
$_SESSION['login_mode'] = 'form';
}
break;
case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS:
if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form'))
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
$_SESSION['login_mode'] = 'form';
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
{
if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER))
{
// X-Combodo-Ajax is a special header automatically added to all ajax requests
// Let's reply that we're currently logged-out
header('HTTP/1.0 401 Unauthorized');
exit;
}
// No credentials yet, display the form
$oPage = LoginWebPage::NewLoginWebPage();
$oPage->DisplayLoginForm('form', $this->bForceFormOnError);
$oPage->output();
$this->bForceFormOnError = false;
exit;
}
}
break;
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
if ($_SESSION['login_mode'] == 'form')
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
break;
case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK:
if ($_SESSION['login_mode'] == 'form')
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
break;
case LoginWebPage::LOGIN_STATE_ERROR:
if ($_SESSION['login_mode'] == 'form')
{
$this->bForceFormOnError = true;
}
break;
case LoginWebPage::LOGIN_STATE_CONNECTED:
if ($_SESSION['login_mode'] == 'form')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
break;
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
/**
* Return the list of supported login modes for this plugin
*
@@ -116,4 +20,87 @@ class LoginForm implements iLoginFSMExtension
{
return array('form');
}
protected function OnModeDetection(&$iErrorCode)
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd))
{
$_SESSION['login_mode'] = 'form';
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnReadCredentials(&$iErrorCode)
{
if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form'))
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
$_SESSION['login_mode'] = 'form';
if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd))
{
if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER))
{
// X-Combodo-Ajax is a special header automatically added to all ajax requests
// Let's reply that we're currently logged-out
header('HTTP/1.0 401 Unauthorized');
exit;
}
// No credentials yet, display the form
$oPage = LoginWebPage::NewLoginWebPage();
$oPage->DisplayLoginForm('form', $this->bForceFormOnError);
$oPage->output();
$this->bForceFormOnError = false;
exit;
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCheckCredentials(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'form')
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCredentialsOK(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'form')
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnError(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'form')
{
$this->bForceFormOnError = true;
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'form')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
}

View File

@@ -7,7 +7,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
class LoginURL implements iLoginFSMExtension
class LoginURL extends AbstractLoginFSMExtension
{
/**
* @var bool
@@ -24,76 +24,61 @@ class LoginURL implements iLoginFSMExtension
return array('url');
}
/**
* Execute action for this login state
* If a page is displayed, the action must exit at this point
*
* @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...)
* @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...)
*
* @return int LoginWebPage::LOGIN_FSM_RETURN_...
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
public function LoginAction($sLoginState, &$iErrorCode)
protected function OnModeDetection(&$iErrorCode)
{
switch ($sLoginState)
if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred)
{
case LoginWebPage::LOGIN_STATE_MODE_DETECTION:
if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred)
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd))
{
$_SESSION['login_mode'] = 'url';
}
}
break;
case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS:
if ($_SESSION['login_mode'] == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
break;
case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK:
if ($_SESSION['login_mode'] == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
break;
case LoginWebPage::LOGIN_STATE_ERROR:
if ($_SESSION['login_mode'] == 'url')
{
$this->bErrorOccurred = true;
}
break;
case LoginWebPage::LOGIN_STATE_CONNECTED:
if ($_SESSION['login_mode'] == 'url')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
break;
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!empty($sAuthUser) && !empty($sAuthPwd))
{
$_SESSION['login_mode'] = 'url';
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCheckCredentials(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal'))
{
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_RETURN_ERROR;
}
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnCredentialsOK(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnError(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'url')
{
$this->bErrorOccurred = true;
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
protected function OnConnected(&$iErrorCode)
{
if ($_SESSION['login_mode'] == 'url')
{
$_SESSION['can_logoff'] = true;
return LoginWebPage::CheckLoggedUser($iErrorCode);
}
return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE;
}
}

View File

@@ -49,7 +49,7 @@ class LoginWebPage extends NiceWebPage
const LOGIN_STATE_MODE_DETECTION = 'login mode detection'; // Detect which login plugin to use
const LOGIN_STATE_READ_CREDENTIALS = 'read credentials'; // Read the credentials
const LOGIN_STATE_CHECK_CREDENTIALS = 'check credentials'; // Check if the credentials are valid
const LOGIN_STATE_CREDENTIAL_OK = 'credentials ok'; // User provisioning
const LOGIN_STATE_CREDENTIALS_OK = 'credentials ok'; // User provisioning
const LOGIN_STATE_USER_OK = 'user ok'; // Additional check (2FA)
const LOGIN_STATE_CONNECTED = 'connected'; // User connected
const LOGIN_STATE_SET_ERROR = 'prepare for error'; // Internal state to trigger ERROR state
@@ -453,6 +453,28 @@ EOF
$this->add("</div>\n");
}
public function DisplayLogoutPage($bPortal)
{
$sUrl = utils::GetAbsoluteUrlAppRoot();
if ($bPortal)
{
$sUrl .= 'portal/';
}
else
{
$sUrl .= 'pages/UI.php';
}
$this->no_cache();
$this->DisplayLoginHeader();
$this->add("<div id=\"login\">\n");
$this->add("<h1>".Dict::S('UI:LogOff:ThankYou')."</h1>\n");
$this->add("<p><a href=\"$sUrl\">".Dict::S('UI:LogOff:ClickHereToLoginAgain')."</a></p>");
$this->add("</div>\n");
$this->output();
}
static function ResetSession()
{
// Unset all of the session variables.
@@ -584,34 +606,36 @@ EOF
* Get plugins list ordered by config 'allowed_login_types'
* Use the login mode to filter plugins
*
* @param string $sInterface 'iLoginFSMExtension' or 'iLogoutExtension'
*
* @return array of plugins
*/
private static function GetLoginPluginList()
public static function GetLoginPluginList($sInterface = 'iLoginFSMExtension')
{
$aAllPlugins = array();
// Keep only the plugins for the current login mode
$sCurrentLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : '';
/** @var iLoginFSMExtension $oLoginFSMExtensionInstance */
foreach (MetaModel::EnumPlugins('iLoginFSMExtension') as $oLoginFSMExtensionInstance)
/** @var iLoginExtension $oLoginExtensionInstance */
foreach (MetaModel::EnumPlugins($sInterface) as $oLoginExtensionInstance)
{
$aLoginModes = $oLoginFSMExtensionInstance->ListSupportedLoginModes();
$aLoginModes = $oLoginExtensionInstance->ListSupportedLoginModes();
foreach ($aLoginModes as $sLoginMode)
{
if (empty($sCurrentLoginMode) || ($sLoginMode == 'default') || ($sLoginMode == $sCurrentLoginMode))
if (empty($sCurrentLoginMode) || ($sLoginMode == 'before') || ($sLoginMode == 'after') || ($sLoginMode == $sCurrentLoginMode))
{
if (!isset($aAllPlugins[$sLoginMode]))
{
$aAllPlugins[$sLoginMode] = array();
}
$aAllPlugins[$sLoginMode][] = $oLoginFSMExtensionInstance;
$aAllPlugins[$sLoginMode][] = $oLoginExtensionInstance;
}
}
}
// Order by the config list of allowed types
$aAllowedLoginModes = array_merge(array('default'), MetaModel::GetConfig()->GetAllowedLoginTypes());
$aAllowedLoginModes = array_merge(array('before'), MetaModel::GetConfig()->GetAllowedLoginTypes(), array('after'));
$aPlugins = array();
foreach ($aAllowedLoginModes as $sAllowedMode)
{
@@ -644,9 +668,9 @@ EOF
return self::LOGIN_STATE_CHECK_CREDENTIALS;
case self::LOGIN_STATE_CHECK_CREDENTIALS:
return self::LOGIN_STATE_CREDENTIAL_OK;
return self::LOGIN_STATE_CREDENTIALS_OK;
case self::LOGIN_STATE_CREDENTIAL_OK:
case self::LOGIN_STATE_CREDENTIALS_OK:
return self::LOGIN_STATE_USER_OK;
case self::LOGIN_STATE_USER_OK:

View File

@@ -2780,7 +2780,7 @@ abstract class MetaModel
// Build the list of available extensions
//
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iLogoutExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();

View File

@@ -43,22 +43,23 @@ if ($operation == 'do_logoff')
exit;
}
if ($bPortal)
{
$sUrl .= 'portal/';
}
else
{
$sUrl .= 'pages/UI.php';
}
if (isset($_SESSION['auth_user']))
{
$sAuthUser = $_SESSION['auth_user'];
UserRights::Login($sAuthUser); // Set the user's language
}
$sLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : '';
LoginWebPage::ResetSession();
$aPluginList = LoginWebPage::GetLoginPluginList('iLogoutExtension');
/** @var iLogoutExtension $oLogoutExtension */
foreach ($aPluginList as $oLogoutExtension)
{
$oLogoutExtension->LogoutAction();
}
/*
switch($sLoginMode)
{
case 'cas':
@@ -71,13 +72,7 @@ switch($sLoginMode)
phpCAS::logoutWithRedirectService($sCASLogoutUrl); // Redirects to the CAS logout page
break;
}
$oPage = LoginWebPage::NewLoginWebPage();
$oPage->no_cache();
$oPage->DisplayLoginHeader();
$oPage->add("<div id=\"login\">\n");
$oPage->add("<h1>".Dict::S('UI:LogOff:ThankYou')."</h1>\n");
*/
$oPage->add("<p><a href=\"$sUrl\">".Dict::S('UI:LogOff:ClickHereToLoginAgain')."</a></p>");
$oPage->add("</div>\n");
$oPage->output();
?>
$oPage = LoginWebPage::NewLoginWebPage();
$oPage->DisplayLogoutPage($bPortal);