improve code

This commit is contained in:
Daniel Seifert 2022-10-31 23:17:04 +01:00
parent 3baffaef2d
commit 5ed13d13d9
Signed by: DanielS
GPG Key ID: 6A513E13AEE66170
19 changed files with 229 additions and 417 deletions

View File

@ -107,7 +107,7 @@ class d3user_webauthn extends AdminDetailsController
$publicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions
); );
} catch (WebauthnException $e) { } catch (WebauthnException $e) {
// ToDo: log exc message // ToDo: log exc message and show message
} }
$this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('isAdmin', isAdmin());

View File

@ -22,16 +22,17 @@ use D3\Webauthn\Application\Model\WebauthnErrors;
use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Application\Model\WebauthnException;
use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent; use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent;
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
use Exception; use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException;
use OxidEsales\Eshop\Application\Controller\Admin\AdminController; use OxidEsales\Eshop\Application\Controller\Admin\AdminController;
use OxidEsales\Eshop\Application\Controller\Admin\LoginController; use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
use OxidEsales\Eshop\Application\Controller\FrontendController; use OxidEsales\Eshop\Application\Controller\FrontendController;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Utils; use OxidEsales\Eshop\Core\Utils;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class d3webauthnadminlogin extends AdminController class d3webauthnadminlogin extends AdminController
{ {
@ -44,8 +45,10 @@ class d3webauthnadminlogin extends AdminController
/** /**
* @return null * @return null
* @throws DatabaseConnectionException * @throws ContainerExceptionInterface
* @throws DatabaseErrorException * @throws DoctrineDriverException
* @throws DoctrineException
* @throws NotFoundExceptionInterface
*/ */
public function render() public function render()
{ {
@ -62,11 +65,16 @@ class d3webauthnadminlogin extends AdminController
$this->generateCredentialRequest(); $this->generateCredentialRequest();
//$this->addTplParam('navFormParams', Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS));
return parent::render(); return parent::render();
} }
/**
* @return void
* @throws DoctrineDriverException
* @throws DoctrineException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function generateCredentialRequest() public function generateCredentialRequest()
{ {
try { try {
@ -78,7 +86,11 @@ class d3webauthnadminlogin extends AdminController
$this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions);
$this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('isAdmin', isAdmin());
} catch (WebauthnException $e) { } catch (WebauthnException $e) {
// ToDo write exc message to display and log Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED'));
Registry::getUtilsView()->addErrorToDisplay($exception);
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
$this->getUtils()->redirect('index.php?cl=login');
} }
} }

View File

@ -22,6 +22,7 @@ use D3\Webauthn\Application\Model\WebauthnErrors;
use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Application\Model\WebauthnException;
use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent; use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent;
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException; use Doctrine\DBAL\Exception as DoctrineException;
use OxidEsales\Eshop\Application\Controller\FrontendController; use OxidEsales\Eshop\Application\Controller\FrontendController;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
@ -39,8 +40,12 @@ class d3webauthnlogin extends FrontendController
/** /**
* @return null * @return null
* @throws ContainerExceptionInterface
* @throws DatabaseConnectionException * @throws DatabaseConnectionException
* @throws DatabaseErrorException * @throws DatabaseErrorException
* @throws DoctrineDriverException
* @throws DoctrineException
* @throws NotFoundExceptionInterface
*/ */
public function render() public function render()
{ {
@ -64,7 +69,7 @@ class d3webauthnlogin extends FrontendController
/** /**
* @return void * @return void
* @throws \Doctrine\DBAL\Driver\Exception * @throws DoctrineDriverException
* @throws DoctrineException * @throws DoctrineException
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
@ -78,7 +83,11 @@ class d3webauthnlogin extends FrontendController
$publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId); $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId);
$this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions);
} catch (WebauthnException $e) { } catch (WebauthnException $e) {
// ToDo: write exc msg to display and log Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED'));
Registry::getUtilsView()->addErrorToDisplay($exception);
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
$this->getUtils()->redirect('index.php?cl=start');
} }
$this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('isAdmin', isAdmin());

View File

@ -186,7 +186,8 @@ class Webauthn
*/ */
public function isActive($userId): bool public function isActive($userId): bool
{ {
return false == Registry::getConfig()->getConfigParam('blDisableWebauthnGlobally') return !Registry::getConfig()->getConfigParam(WebauthnConf::GLOBAL_SWITCH)
&& !Registry::getSession()->getVariable(WebauthnConf::GLOBAL_SWITCH)
&& $this->UserUseWebauthn($userId); && $this->UserUseWebauthn($userId);
} }

View File

@ -23,4 +23,6 @@ class WebauthnConf
public const WEBAUTHN_SESSION_LOGINUSER = 'd3webauthnLoginUser'; // username entered in login form public const WEBAUTHN_SESSION_LOGINUSER = 'd3webauthnLoginUser'; // username entered in login form
public const WEBAUTHN_SESSION_CURRENTCLASS = 'd3webauthnCurrentClass'; // no usage public const WEBAUTHN_SESSION_CURRENTCLASS = 'd3webauthnCurrentClass'; // no usage
public const WEBAUTHN_SESSION_NAVFORMPARAMS = 'd3webauthnNavFormParams'; // no usage public const WEBAUTHN_SESSION_NAVFORMPARAMS = 'd3webauthnNavFormParams'; // no usage
public const GLOBAL_SWITCH = 'blDisableWebauthnGlobally';
} }

View File

@ -28,4 +28,6 @@ $aLang = array(
'D3_WEBAUTHN_ACCOUNT_TYPE1' => 'nur Auth-Stick', 'D3_WEBAUTHN_ACCOUNT_TYPE1' => 'nur Auth-Stick',
'D3_WEBAUTHN_ACCOUNT_TYPE2' => 'nur Auth-Stick, Passwort als Alternative', 'D3_WEBAUTHN_ACCOUNT_TYPE2' => 'nur Auth-Stick, Passwort als Alternative',
'D3_WEBAUTHN_ACCOUNT_TYPE3' => 'Auth-Stick und Passwort in Kombination', 'D3_WEBAUTHN_ACCOUNT_TYPE3' => 'Auth-Stick und Passwort in Kombination',
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Die Anmeldung mit Sicherheitsschlüssel ist aus technischen Gründen derzeit leider nicht möglich. Bitte verwenden Sie statt dessen Ihr Passwort.',
); );

View File

@ -46,4 +46,6 @@ $aLang = [
'D3_WEBAUTHN_ERR_NOTSUPPORTED' => 'Die Aktion wird nicht unterstützt.', 'D3_WEBAUTHN_ERR_NOTSUPPORTED' => 'Die Aktion wird nicht unterstützt.',
'D3_WEBAUTHN_ERR_UNKNOWN' => 'Die Aktion wurde wegen eines unbekannten Fehlers abgebrochen.', 'D3_WEBAUTHN_ERR_UNKNOWN' => 'Die Aktion wurde wegen eines unbekannten Fehlers abgebrochen.',
'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Ihr Browser unterstützt die Verwendung von Hardwareschlüsseln leider nicht.', 'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Ihr Browser unterstützt die Verwendung von Hardwareschlüsseln leider nicht.',
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Die Anmeldung mit Sicherheitsschlüssel ist aus technischen Gründen derzeit leider nicht möglich. Bitte verwenden Sie statt dessen Ihr Passwort.',
]; ];

View File

@ -47,4 +47,5 @@ $aLang = [
'D3_WEBAUTHN_ERR_UNKNOWN' => 'The action was cancelled due to an unknown error.', 'D3_WEBAUTHN_ERR_UNKNOWN' => 'The action was cancelled due to an unknown error.',
'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Unfortunately, your browser does not support the use of hardware keys.', 'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Unfortunately, your browser does not support the use of hardware keys.',
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Unfortunately, logging in with a security key is currently not possible for technical reasons. Please use your password instead.',
]; ];

View File

@ -24,14 +24,10 @@ namespace D3\Webauthn\Modules\Application\Component
namespace D3\Webauthn\Modules\Application\Controller namespace D3\Webauthn\Modules\Application\Controller
{ {
use OxidEsales\Eshop\Application\Controller\OrderController; use OxidEsales\Eshop\Application\Controller\OrderController;
use OxidEsales\Eshop\Application\Controller\PaymentController; use OxidEsales\Eshop\Application\Controller\PaymentController;
use OxidEsales\Eshop\Application\Controller\StartController;
use OxidEsales\Eshop\Application\Controller\UserController; use OxidEsales\Eshop\Application\Controller\UserController;
class d3_StartController_Webauthn_parent extends StartController {}
class d3_webauthn_UserController_parent extends UserController {} class d3_webauthn_UserController_parent extends UserController {}
class d3_webauthn_OrderController_parent extends OrderController {} class d3_webauthn_OrderController_parent extends OrderController {}

View File

@ -19,6 +19,7 @@ use Assert\AssertionFailedException;
use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnConf;
use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Application\Model\WebauthnException;
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Query\QueryBuilder;
@ -43,7 +44,9 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
public function login_noredirect() public function login_noredirect()
{ {
$lgn_user = Registry::getRequest()->getRequestParameter('lgn_usr'); $lgn_user = Registry::getRequest()->getRequestParameter('lgn_usr');
$userId = $this->d3GetLoginUserId($lgn_user); /** @var d3_User_Webauthn $user */
$user = oxNew(User::class);
$userId = $user->d3GetLoginUserId($lgn_user);
if ($lgn_user && $userId) { if ($lgn_user && $userId) {
$webauthn = $this->d3GetWebauthnObject(); $webauthn = $this->d3GetWebauthnObject();
@ -63,8 +66,6 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
$this->getParent()->getViewConfig()->getNavFormParams() $this->getParent()->getViewConfig()->getNavFormParams()
); );
//$oUser->d3templogout();
return "d3webauthnlogin"; return "d3webauthnlogin";
} }
} }
@ -80,29 +81,6 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
return oxNew(Webauthn::class); return oxNew(Webauthn::class);
} }
/**
* @return bool|string
*/
public function checkWebauthnlogin()
{
$sWebauth = base64_decode(Registry::getRequest()->getRequestParameter('keyauth'));
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
$oUser = oxNew(User::class);
$oUser->load($userId);
$webauthn = $this->d3GetWebauthnObject();
if (!$this->isNoWebauthnOrNoLogin($webauthn, $userId) && $this->hasValidWebauthn($sWebauth, $webauthn)) {
$this->d3WebauthnRelogin($oUser, $sWebauth);
$this->d3WebauthnClearSessionVariables();
return false;
}
return 'd3webauthnlogin';
}
/** /**
* @return UtilsView * @return UtilsView
*/ */
@ -111,7 +89,7 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
return Registry::getUtilsView(); return Registry::getUtilsView();
} }
public function cancelWebauthnLogin() public function cancelWebauthnLogin(): bool
{ {
$this->d3WebauthnClearSessionVariables(); $this->d3WebauthnClearSessionVariables();
@ -151,16 +129,29 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
} }
/** /**
* @param User $oUser * @param User $user
* @param $sWebauthn * @param $sWebauthn
*/ */
public function d3WebauthnRelogin(User $oUser, $sWebauthn) public function d3WebauthnRelogin(User $user, $sWebauthn)
{ {
$setSessionCookie = Registry::getRequest()->getRequestParameter('lgn_cook');
$this->d3GetSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $sWebauthn); $this->d3GetSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $sWebauthn);
$this->d3GetSession()->setVariable('usr', $oUser->getId()); $this->d3GetSession()->setVariable('usr', $user->getId());
$this->setUser(null); $this->setUser(null);
$this->setLoginStatus(USER_LOGIN_SUCCESS); $this->setLoginStatus(USER_LOGIN_SUCCESS);
$this->_afterLogin($oUser);
// cookie must be set ?
if ($setSessionCookie && Registry::getConfig()->getConfigParam('blShowRememberMe')) {
Registry::getUtilsServer()->setUserCookie(
$user->oxuser__oxusername->value,
$user->oxuser__oxpassword->value,
Registry::getConfig()->getShopId(),
31536000,
User::USER_COOKIE_SALT
);
}
$this->_afterLogin($user);
} }
public function d3WebauthnClearSessionVariables() public function d3WebauthnClearSessionVariables()
@ -178,39 +169,4 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
{ {
return Registry::getSession(); return Registry::getSession();
} }
/**
* @return string|null
* @throws DoctrineDriverException
* @throws Exception
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function d3GetLoginUserId($username): ?string
{
if (empty($username)) {
return null;
}
$user = oxNew(User::class);
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('oxid')
->from($user->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxusername',
$qb->createNamedParameter($username)
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
)
)
)->setMaxResults(1);
return $qb->execute()->fetchOne();
}
} }

View File

@ -17,6 +17,7 @@ namespace D3\Webauthn\Modules\Application\Controller\Admin;
use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnConf;
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
use Doctrine\DBAL\Driver\Exception as DoctrineException; use Doctrine\DBAL\Driver\Exception as DoctrineException;
use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Query\QueryBuilder;
@ -50,10 +51,16 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
*/ */
public function checklogin() public function checklogin()
{ {
$lgn_user = Registry::getRequest()->getRequestParameter('user'); $lgn_user = Registry::getRequest()->getRequestParameter('user') ?:
$userId = $this->d3GetLoginUserId($lgn_user); Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER);
if ($lgn_user && $userId && false === Registry::getSession()->hasVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) { /** @var d3_User_Webauthn $user */
$user = $this->d3GetUserObject();
$userId = $user->d3GetLoginUserId($lgn_user, 'malladmin');
if ($lgn_user && $userId &&
false === Registry::getSession()->hasVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)
) {
$webauthn = $this->d3GetWebauthnObject(); $webauthn = $this->d3GetWebauthnObject();
if ($webauthn->isActive($userId) if ($webauthn->isActive($userId)
@ -72,14 +79,6 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
$lgn_user $lgn_user
); );
/*
Registry::getSession()->setVariable(
WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS,
$this->getViewConfig()->getNavFormParams()
);
*/
//$oUser->d3templogout();
return "d3webauthnadminlogin"; return "d3webauthnadminlogin";
} }
} }
@ -87,46 +86,6 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
return parent::checklogin(); return parent::checklogin();
} }
/**
* @param $username
* @return string|null
* @throws DoctrineException
* @throws Exception
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function d3GetLoginUserId($username): ?string
{
if (empty($username)) {
return null;
}
$user = oxNew(User::class);
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('oxid')
->from($user->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxusername',
$qb->createNamedParameter($username)
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
),
$qb->expr()->eq(
'oxrights',
$qb->createNamedParameter('malladmin')
)
)
)->setMaxResults(1);
return $qb->execute()->fetchOne();
}
public function d3WebauthnCancelLogin() public function d3WebauthnCancelLogin()
{ {
$oUser = $this->d3GetUserObject(); $oUser = $this->d3GetUserObject();
@ -136,7 +95,7 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
/** /**
* @return User * @return User
*/ */
public function d3GetUserObject() public function d3GetUserObject(): User
{ {
return oxNew(User::class); return oxNew(User::class);
} }

View File

@ -15,7 +15,6 @@
namespace D3\Webauthn\Modules\Application\Controller; namespace D3\Webauthn\Modules\Application\Controller;
class d3_webauthn_OrderController extends d3_webauthn_OrderController_parent class d3_webauthn_OrderController extends d3_webauthn_OrderController_parent
{ {
use d3_webauthn_getUserTrait; use d3_webauthn_getUserTrait;

View File

@ -15,7 +15,6 @@
namespace D3\Webauthn\Modules\Application\Controller; namespace D3\Webauthn\Modules\Application\Controller;
class d3_webauthn_PaymentController extends d3_webauthn_PaymentController_parent class d3_webauthn_PaymentController extends d3_webauthn_PaymentController_parent
{ {
use d3_webauthn_getUserTrait; use d3_webauthn_getUserTrait;

View File

@ -15,7 +15,6 @@
namespace D3\Webauthn\Modules\Application\Controller; namespace D3\Webauthn\Modules\Application\Controller;
class d3_webauthn_UserController extends d3_webauthn_UserController_parent class d3_webauthn_UserController extends d3_webauthn_UserController_parent
{ {
use d3_webauthn_getUserTrait; use d3_webauthn_getUserTrait;

View File

@ -17,14 +17,22 @@ namespace D3\Webauthn\Modules\Application\Controller;
use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnConf;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception as DoctrineException;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session; use OxidEsales\Eshop\Core\Session;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
trait d3_webauthn_getUserTrait trait d3_webauthn_getUserTrait
{ {
/** /**
* @return bool|object|User * @return bool|object|User
* @throws Exception
* @throws DoctrineException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/ */
public function getUser() public function getUser()
{ {
@ -34,7 +42,7 @@ trait d3_webauthn_getUserTrait
$webauthn = $this->d3GetWebauthnpObject(); $webauthn = $this->d3GetWebauthnpObject();
if ($webauthn->isActive($user->getId()) if ($webauthn->isActive($user->getId())
&& false == $this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) && !$this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)
) { ) {
return false; return false;
} }
@ -46,7 +54,7 @@ trait d3_webauthn_getUserTrait
/** /**
* @return Webauthn * @return Webauthn
*/ */
public function d3GetWebauthnObject() public function d3GetWebauthnObject(): Webauthn
{ {
return oxNew(Webauthn::class); return oxNew(Webauthn::class);
} }
@ -54,7 +62,7 @@ trait d3_webauthn_getUserTrait
/** /**
* @return Session * @return Session
*/ */
public function d3GetSessionObject() public function d3GetSessionObject(): Session
{ {
return Registry::getSession(); return Registry::getSession();
} }

View File

@ -16,7 +16,15 @@
namespace D3\Webauthn\Modules\Application\Model; namespace D3\Webauthn\Modules\Application\Model;
use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnConf;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder;
use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionClass; use ReflectionClass;
class d3_User_Webauthn extends d3_User_Webauthn_parent class d3_User_Webauthn extends d3_User_Webauthn_parent
@ -35,27 +43,6 @@ class d3_User_Webauthn extends d3_User_Webauthn_parent
return $return; return $return;
} }
public function d3templogout()
{
$varname = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH);
$object = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT);
$currentUser = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
$currentClass = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS);
$navFormParams = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS);
$loginUser = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER);
$return = $this->logout();
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $varname);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $object);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $currentUser);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, $currentClass);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS, $navFormParams);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER, $loginUser);
return $return;
}
public function login($userName, $password, $setSessionCookie = false) public function login($userName, $password, $setSessionCookie = false)
{ {
if (Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) { if (Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) {
@ -78,4 +65,43 @@ class d3_User_Webauthn extends d3_User_Webauthn_parent
return parent::login($userName, $password, $setSessionCookie); return parent::login($userName, $password, $setSessionCookie);
} }
/**
* @param string $username
* @param ?string $rights
* @return string|null
* @throws ContainerExceptionInterface
* @throws DoctrineDriverException
* @throws Exception
* @throws NotFoundExceptionInterface
*/
public function d3GetLoginUserId(string $username, string $rights = null): ?string
{
if (empty($username)) {
return null;
}
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('oxid')
->from($this->getViewName())
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxusername',
$qb->createNamedParameter($username)
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
),
$rights ? $qb->expr()->eq(
'oxrights',
$qb->createNamedParameter($rights)
) : '1'
)
)->setMaxResults(1);
return $qb->execute()->fetchOne();
}
} }

View File

@ -18,16 +18,22 @@ namespace D3\Webauthn\Modules\Core;
use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnConf;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception as DoctrineException;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session; use OxidEsales\Eshop\Core\Session;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class d3_webauthn_utils extends d3_webauthn_utils_parent class d3_webauthn_utils extends d3_webauthn_utils_parent
{ {
/** /**
* @return bool * @return bool
* @throws DBALException * @throws Exception
* @throws DatabaseConnectionException * @throws DoctrineException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/ */
public function checkAccessRights() public function checkAccessRights()
{ {
@ -35,12 +41,11 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
$userID = $this->d3GetSessionObject()->getVariable("auth"); $userID = $this->d3GetSessionObject()->getVariable("auth");
$webauthnAuth = (bool) $this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH); $webauthnAuth = (bool) $this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH);
/** @var Webauthn $webauthn */
$webauthn = $this->d3GetWebauthnObject(); $webauthn = $this->d3GetWebauthnObject();
if ($blAuth && $webauthn->isActive($userID) && false === $webauthnAuth) { if ($blAuth && $webauthn->isActive($userID) && false === $webauthnAuth) {
$this->redirect('index.php?cl=login', true, 302); $this->redirect('index.php?cl=login', true, 302);
if (false == defined('OXID_PHP_UNIT')) { if (!defined('OXID_PHP_UNIT')) {
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
exit; exit;
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
@ -53,7 +58,7 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
/** /**
* @return Session * @return Session
*/ */
public function d3GetSessionObject() public function d3GetSessionObject(): Session
{ {
return Registry::getSession(); return Registry::getSession();
} }
@ -61,7 +66,7 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
/** /**
* @return Webauthn * @return Webauthn
*/ */
public function d3GetWebauthnObject() public function d3GetWebauthnObject(): Webauthn
{ {
return oxNew(Webauthn::class); return oxNew(Webauthn::class);
} }

View File

@ -17,9 +17,20 @@
namespace D3\Webauthn\Setup; namespace D3\Webauthn\Setup;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException;
use Doctrine\DBAL\Query\QueryBuilder;
use Exception;
use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\DbMetaDataHandler; use OxidEsales\Eshop\Core\DbMetaDataHandler;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\UtilsView;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class Events class Events
{ {
@ -44,6 +55,9 @@ class Events
/** /**
* Execute action on activate event * Execute action on activate event
* @return void
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/ */
public static function onActivate() public static function onActivate()
{ {
@ -52,6 +66,8 @@ class Events
self::regenerateViews(); self::regenerateViews();
self::clearCache(); self::clearCache();
self::seoUrl();
} }
public static function onDeactivate() public static function onDeactivate()
@ -60,6 +76,9 @@ class Events
/** /**
* Execute the sql at the first time of the module installation. * Execute the sql at the first time of the module installation.
* @return void
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/ */
private static function setupModule() private static function setupModule()
{ {
@ -75,7 +94,7 @@ class Events
* *
* @return bool * @return bool
*/ */
protected static function tableExists($sTableName) protected static function tableExists(string $sTableName): bool
{ {
$oDbMetaDataHandler = oxNew(DbMetaDataHandler::class ); $oDbMetaDataHandler = oxNew(DbMetaDataHandler::class );
@ -86,6 +105,8 @@ class Events
* Executes given sql statement. * Executes given sql statement.
* *
* @param string $sSQL Sql to execute. * @param string $sSQL Sql to execute.
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/ */
private static function executeSQL($sSQL) private static function executeSQL($sSQL)
{ {
@ -100,7 +121,7 @@ class Events
* *
* @return bool * @return bool
*/ */
protected static function fieldExists($sFieldName, $sTableName) protected static function fieldExists(string $sFieldName, string $sTableName): bool
{ {
$oDbMetaDataHandler = oxNew(DbMetaDataHandler::class ); $oDbMetaDataHandler = oxNew(DbMetaDataHandler::class );
@ -117,11 +138,11 @@ class Events
} }
/** /**
* Empty cache * clear cache
*/ */
private static function clearCache() private static function clearCache()
{ {
/** @var \OxidEsales\Eshop\Core\UtilsView $oUtilsView */ /** @var UtilsView $oUtilsView */
$oUtilsView = Registry::getUtilsView(); $oUtilsView = Registry::getUtilsView();
$sSmartyDir = $oUtilsView->getSmartyDir(); $sSmartyDir = $oUtilsView->getSmartyDir();
@ -133,4 +154,65 @@ class Events
} }
} }
} }
/**
* @return void
*/
private static function seoUrl()
{
try {
if (!self::hasSeoUrl()) {
self::createSeoUrl();
}
} catch (Exception|NotFoundExceptionInterface|DoctrineDriverException|ContainerExceptionInterface $e) {
Registry::getUtilsView()->addErrorToDisplay('error wile creating SEO URLs: '.$e->getMessage());
}
}
/**
* @return bool
* @throws DoctrineDriverException
* @throws DoctrineException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private static function hasSeoUrl(): bool
{
/** @var QueryBuilder $qb */
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$qb->select('1')
->from('oxseo')
->where(
$qb->expr()->and(
$qb->expr()->eq(
'oxstdurl',
$qb->createNamedParameter('index.php?cl=d3_account_webauthn')
),
$qb->expr()->eq(
'oxshopid',
$qb->createNamedParameter(Registry::getConfig()->getShopId())
),
$qb->expr()->eq(
'oxlang',
$qb->createNamedParameter('1')
)
)
)
->setMaxResults(1);
return $qb->execute()->fetchOne();
}
/**
* @return void
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
private static function createSeoUrl()
{
$query = "INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
('ff57646b47249ee33c6b672741ac371a', 'be07f06fe03a4d5d7936f2eac5e3a87b', 1, 1, 'index.php?cl=d3_account_webauthn', 'en/key-authintication/', 'static', 0, 0, '', NOW()),
('ff57646b47249ee33c6b672741ac371a', '220a1af77362196789eeed4741dda184', 1, 0, 'index.php?cl=d3_account_webauthn', 'key-authentisierung/', 'static', 0, 0, '', NOW());";
DatabaseProvider::getDb()->execute($query);
}
} }

View File

@ -1,246 +0,0 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\Webauthn\Setup;
use D3\ModCfg\Application\Model\d3database;
use D3\ModCfg\Application\Model\Install\d3install_updatebase;
use Doctrine\DBAL\DBALException;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\ConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
class Installation extends d3install_updatebase
{
protected $_aUpdateMethods = array(
array('check' => 'doesPublicKeyCredentialTableNotExist',
'do' => 'addPublicKeyCredentialTable'),
array('check' => 'checkFields',
'do' => 'fixFields'),
array('check' => 'checkIndizes',
'do' => 'fixIndizes'),
array('check' => 'checkSEONotExists',
'do' => 'addSEO'),
);
public $aMultiLangTables = array();
public $aFields = array(
'OXID' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'OXID',
'sType' => 'CHAR(32)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'NAME' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'Name',
'sType' => 'VARCHAR(255)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'CREDENTIALID' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'CredentialId',
'sType' => 'BINARY(48)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'TYPE' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'Type',
'sType' => 'CHAR(20)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'TRANSPORTS' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'Transports',
'sType' => 'VARCHAR(255)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'ATTESTATIONTYPE' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'AttestationType',
'sType' => 'CHAR(100)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'TRUSTPATH' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'TrustPath',
'sType' => 'VARCHAR(255)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'AAGUID' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'Aaguid',
'sType' => 'VARCHAR(255)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'PUBLICKEY' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'PublicKey',
'sType' => 'BINARY(77)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'USERHANDLE' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'UserHandle',
'sType' => 'CHAR(36)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'COUNTER' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'Counter',
'sType' => 'INT(5)',
'blNull' => false,
'sDefault' => false,
'sComment' => '',
'sExtra' => '',
'blMultilang' => false,
),
'OXTIMESTAMP' => array(
'sTableName' => 'd3PublicKeyCredential',
'sFieldName' => 'oxtimestamp',
'sType' => 'TIMESTAMP',
'blNull' => false,
'sDefault' => 'CURRENT_TIMESTAMP',
'sComment' => 'Timestamp',
'sExtra' => '',
'blMultilang' => false,
)
);
public $aIndizes = array(
'OXID' => array(
'sTableName' => 'd3PublicKeyCredential',
'sType' => d3database::INDEX_TYPE_PRIMARY,
'sName' => 'PRIMARY',
'aFields' => array(
'OXID' => 'OXID',
),
),
'OXUSERID' => array(
'sTableName' => 'd3PublicKeyCredential',
'sType' => d3database::INDEX_TYPE_UNIQUE,
'sName' => 'CredentialId',
'aFields' => array(
'CredentialId' => 'CredentialId',
),
)
);
protected $_aRefreshMetaModuleIds = array('d3webauthn');
/**
* @return bool
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function doesPublicKeyCredentialTableNotExist()
{
return $this->_checkTableNotExist('d3PublicKeyCredential');
}
/**
* @return bool
* @throws ConnectionException
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function addPublicKeyCredentialTable()
{
$blRet = false;
if ($this->doesPublicKeyCredentialTableNotExist()) {
$this->setInitialExecMethod(__METHOD__);
$blRet = $this->_addTable2(
'd3PublicKeyCredential',
$this->aFields,
$this->aIndizes,
'key credentials',
'InnoDB'
);
}
return $blRet;
}
/**
* @return bool
* @throws DatabaseConnectionException
*/
public function checkSEONotExists()
{
$query = "SELECT 1 FROM " . getViewName('oxseo') . " WHERE oxstdurl = 'index.php?cl=d3_account_webauthn'";
return !DatabaseProvider::getDb()->getOne($query);
}
/**
* @return bool
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
public function addSEO()
{
$query = [
"INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
('ff57646b47249ee33c6b672741ac371a', 'be07f06fe03a4d5d7936f2eac5e3a87b', 1, 1, 'index.php?cl=d3_account_webauthn', 'en/key-authintication/', 'static', 0, 0, '', NOW()),
('ff57646b47249ee33c6b672741ac371a', '220a1af77362196789eeed4741dda184', 1, 0, 'index.php?cl=d3_account_webauthn', 'key-authentisierung/', 'static', 0, 0, '', NOW());"
];
return $this->_executeMultipleQueries($query);
}
}