From c86984df5f415b133aa597ec7e7ea03a498f59ad Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Thu, 24 Nov 2022 00:51:56 +0100 Subject: [PATCH] move OTP check from login controller check to onAdminLoginEvent for webauthn compatibility --- .../Controller/Admin/d3totpadminlogin.php | 15 +++- src/Application/Model/d3totp_conf.php | 2 + .../views/admin/tpl/d3totplogin.tpl | 2 + src/IntelliSenseHelper.php | 5 ++ .../Admin/d3_totp_LoginController.php | 51 ++++++++--- src/Modules/Core/totpSystemEventHandler.php | 88 +++++++++++++++++++ src/metadata.php | 3 + 7 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 src/Modules/Core/totpSystemEventHandler.php diff --git a/src/Application/Controller/Admin/d3totpadminlogin.php b/src/Application/Controller/Admin/d3totpadminlogin.php index d305013..d8d1f90 100644 --- a/src/Application/Controller/Admin/d3totpadminlogin.php +++ b/src/Application/Controller/Admin/d3totpadminlogin.php @@ -19,8 +19,10 @@ use D3\Totp\Application\Model\d3backupcodelist; use D3\Totp\Application\Model\d3totp; use D3\Totp\Application\Model\d3totp_conf; use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException; +use D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController; use D3\Totp\Modules\Application\Model\d3_totp_user; use OxidEsales\Eshop\Application\Controller\Admin\AdminController; +use OxidEsales\Eshop\Application\Controller\Admin\LoginController; use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Registry; @@ -85,6 +87,9 @@ class d3totpadminlogin extends AdminController $this->d3TotpGetUtils()->redirect('index.php?cl=login'); } + $this->addTplParam('selectedProfile', Registry::getRequest()->getRequestEscapedParameter('profile')); + $this->addTplParam('selectedChLanguage', Registry::getRequest()->getRequestEscapedParameter('chlanguage')); + return parent::render(); } @@ -154,14 +159,20 @@ class d3totpadminlogin extends AdminController $this->d3TotpHasValidTotp($sTotp, $totp); - $adminProfiles = $session->getVariable("aAdminProfiles"); + $selectedProfile = Registry::getRequest()->getRequestEscapedParameter('profile'); + $selectedLanguage = Registry::getRequest()->getRequestEscapedParameter('chlanguage'); $session->initNewSession(); - $session->setVariable("aAdminProfiles", $adminProfiles); + $session->setVariable(d3totp_conf::SESSION_ADMIN_PROFILE, $selectedProfile); + $session->setVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE, $selectedLanguage); $session->setVariable(d3totp_conf::OXID_ADMIN_AUTH, $userId); $session->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, $userId); $session->deleteVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER); + /** @var d3_totp_LoginController $loginController */ + $loginController = oxNew(LoginController::class); + $loginController->d3totpAfterLogin(); + return "admin_start"; } catch (d3totp_wrongOtpException $e) { Registry::getUtilsView()->addErrorToDisplay($e); diff --git a/src/Application/Model/d3totp_conf.php b/src/Application/Model/d3totp_conf.php index 54b8efa..4aa4273 100644 --- a/src/Application/Model/d3totp_conf.php +++ b/src/Application/Model/d3totp_conf.php @@ -25,4 +25,6 @@ class d3totp_conf public const SESSION_NAVFORMPARAMS = 'd3Totp_navFormParams'; public const SESSION_ADMIN_AUTH = 'd3Totp_auth'; // has valid totp, user is logged in completly public const SESSION_ADMIN_CURRENTUSER = 'd3Totp_currentUser'; // oxid assigned to user from entered username + public const SESSION_ADMIN_PROFILE = 'd3Totp_currentProfile'; // selected profile + public const SESSION_ADMIN_CHLANGUAGE = 'd3Totp_currentChLanguage'; // selected language } \ No newline at end of file diff --git a/src/Application/views/admin/tpl/d3totplogin.tpl b/src/Application/views/admin/tpl/d3totplogin.tpl index 0def3f9..9cd3f9f 100644 --- a/src/Application/views/admin/tpl/d3totplogin.tpl +++ b/src/Application/views/admin/tpl/d3totplogin.tpl @@ -21,6 +21,8 @@ + +

[{oxmultilang ident="TOTP_INPUT"}]

diff --git a/src/IntelliSenseHelper.php b/src/IntelliSenseHelper.php index bab0639..12ffcc2 100644 --- a/src/IntelliSenseHelper.php +++ b/src/IntelliSenseHelper.php @@ -65,8 +65,13 @@ namespace D3\Totp\Modules\Core { use OxidEsales\Eshop\Core\Utils; + use OxidEsales\EshopCommunity\Core\SystemEventHandler; class d3_totp_utils_parent extends Utils { } + + class totpSystemEventHandler_parent extends SystemEventHandler + { + } } diff --git a/src/Modules/Application/Controller/Admin/d3_totp_LoginController.php b/src/Modules/Application/Controller/Admin/d3_totp_LoginController.php index d85afa4..59be402 100644 --- a/src/Modules/Application/Controller/Admin/d3_totp_LoginController.php +++ b/src/Modules/Application/Controller/Admin/d3_totp_LoginController.php @@ -50,24 +50,49 @@ class d3_totp_LoginController extends d3_totp_LoginController_parent */ public function checklogin() { + Registry::getSession()->setVariable( + d3totp_conf::SESSION_ADMIN_PROFILE, + Registry::getRequest()->getRequestEscapedParameter('profile') + ); + Registry::getSession()->setVariable( + d3totp_conf::SESSION_ADMIN_CHLANGUAGE, + Registry::getRequest()->getRequestEscapedParameter('chlanguage') + ); + // parent::checklogin(); - $return = $this->d3CallMockableParent('checklogin'); + return $this->d3CallMockableParent('checklogin'); + } - $totp = $this->d3GetTotpObject(); - $totp->loadByUserId(Registry::getSession()->getVariable("auth")); + public function d3totpAfterLogin() + { + $myUtilsServer = Registry::getUtilsServer(); + $sProfile = Registry::getSession()->getVariable(d3totp_conf::SESSION_ADMIN_PROFILE); - if ($this->d3TotpLoginMissing($totp)) { - $userId = $this->d3TotpGetSession()->getVariable('auth'); - - /** @var d3_totp_user $user */ - $user = $this->d3TotpGetUserObject(); - $user->logout(); - - $this->d3TotpGetSession()->setVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER, $userId); - return "d3totpadminlogin"; + // #533 + if (isset($sProfile)) { + $aProfiles = Registry::getSession()->getVariable("aAdminProfiles"); + if ($aProfiles && isset($aProfiles[$sProfile])) { + // setting cookie to store last locally used profile + $myUtilsServer->setOxCookie("oxidadminprofile", $sProfile . "@" . implode("@", $aProfiles[$sProfile]), time() + 31536000, "/"); + Registry::getSession()->setVariable("profile", $aProfiles[$sProfile]); + Registry::getSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_PROFILE); + } + } else { + //deleting cookie info, as setting profile to default + $myUtilsServer->setOxCookie("oxidadminprofile", "", time() - 3600, "/"); } - return $return; + // languages + $iLang = Registry::getSession()->getVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE); + + $aLanguages = Registry::getLang()->getAdminTplLanguageArray(); + if (!isset($aLanguages[$iLang])) { + $iLang = key($aLanguages); + } + + $myUtilsServer->setOxCookie("oxidadminlanguage", $aLanguages[$iLang]->abbr, time() + 31536000, "/"); + Registry::getLang()->setTplLanguage($iLang); + Registry::getSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE); } /** diff --git a/src/Modules/Core/totpSystemEventHandler.php b/src/Modules/Core/totpSystemEventHandler.php new file mode 100644 index 0000000..da3eaea --- /dev/null +++ b/src/Modules/Core/totpSystemEventHandler.php @@ -0,0 +1,88 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\Totp\Modules\Core; + +use D3\Totp\Application\Model\d3totp; +use D3\Totp\Application\Model\d3totp_conf; +use D3\Totp\Modules\Application\Model\d3_totp_user; +use OxidEsales\Eshop\Application\Model\User; +use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Session; + +class totpSystemEventHandler extends totpSystemEventHandler_parent +{ + public function onAdminLogin() + { + $this->d3RequestTotp(); + + parent::onAdminLogin(); + } + + protected function d3requestTotp() + { + $totp = $this->d3GetTotpObject(); + $userId = $this->d3TotpGetSession()->getVariable('auth'); + $totp->loadByUserId($userId); + + if ($this->d3TotpLoginMissing($totp)) { + /** @var d3_totp_user $user */ + $user = $this->d3TotpGetUserObject(); + $user->logout(); + + $this->d3TotpGetSession()->setVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER, $userId); + + Registry::getUtils()->redirect( + 'index.php?cl=d3totpadminlogin&'. + 'profile='.$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_PROFILE).'&'. + 'chlanguage='.$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE) + ); + } + } + + /** + * @return d3totp + */ + public function d3GetTotpObject() + { + return oxNew(d3totp::class); + } + + /** + * @return Session + */ + public function d3TotpGetSession() + { + return Registry::getSession(); + } + + /** + * @param d3totp $totp + * @return bool + */ + public function d3TotpLoginMissing($totp) + { + return $totp->isActive() + && false == $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_AUTH); + } + + /** + * @return d3_totp_user + */ + protected function d3TotpGetUserObject(): d3_totp_user + { + return oxNew( User::class ); + } +} \ No newline at end of file diff --git a/src/metadata.php b/src/metadata.php index 180d2b4..664abe2 100644 --- a/src/metadata.php +++ b/src/metadata.php @@ -25,12 +25,14 @@ use D3\Totp\Modules\Application\Controller\d3_totp_PaymentController; use D3\Totp\Modules\Application\Controller\d3_totp_UserController; use D3\Totp\Modules\Application\Model\d3_totp_user; use D3\Totp\Modules\Core\d3_totp_utils; +use D3\Totp\Modules\Core\totpSystemEventHandler; use D3\Totp\Setup as ModuleSetup; use OxidEsales\Eshop\Application\Component\UserComponent; use OxidEsales\Eshop\Application\Controller\Admin\LoginController; use OxidEsales\Eshop\Application\Controller\OrderController; use OxidEsales\Eshop\Application\Controller\PaymentController; use OxidEsales\Eshop\Application\Controller\UserController; +use OxidEsales\Eshop\Core\SystemEventHandler; use OxidEsales\Eshop\Core\Utils; use OxidEsales\Eshop\Application\Model as OxidModel; @@ -67,6 +69,7 @@ $aModule = [ LoginController::class => d3_totp_LoginController::class, Utils::class => d3_totp_utils::class, UserComponent::class => d3_totp_UserComponent::class, + SystemEventHandler::class => totpSystemEventHandler::class ], 'controllers' => [ 'd3user_totp' => d3user_totp::class,