diff --git a/src/Application/Controller/Admin/d3user_webauthn.php b/src/Application/Controller/Admin/d3user_webauthn.php index d04f991..ef5449c 100755 --- a/src/Application/Controller/Admin/d3user_webauthn.php +++ b/src/Application/Controller/Admin/d3user_webauthn.php @@ -19,6 +19,7 @@ use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\WebauthnErrors; +use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use Exception; use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController; @@ -94,16 +95,21 @@ class d3user_webauthn extends AdminDetailsController public function setAuthnRegister() { - $authn = oxNew(Webauthn::class); + try { + $authn = oxNew(Webauthn::class); - $user = $this->getUserObject(); - $user->load($this->getEditObjectId()); - $publicKeyCredentialCreationOptions = $authn->getCreationOptions($user); + $user = $this->getUserObject(); + $user->load($this->getEditObjectId()); + $publicKeyCredentialCreationOptions = $authn->getCreationOptions($user); + + $this->addTplParam( + 'webauthn_publickey_create', + $publicKeyCredentialCreationOptions + ); + } catch (WebauthnException $e) { + // ToDo: log exc message + } - $this->addTplParam( - 'webauthn_publickey_create', - $publicKeyCredentialCreationOptions - ); $this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('keyname', Registry::getRequest()->getRequestEscapedParameter('credenialname')); } diff --git a/src/Application/Controller/Admin/d3webauthnadminlogin.php b/src/Application/Controller/Admin/d3webauthnadminlogin.php index 3a8f3ef..a562555 100755 --- a/src/Application/Controller/Admin/d3webauthnadminlogin.php +++ b/src/Application/Controller/Admin/d3webauthnadminlogin.php @@ -15,9 +15,11 @@ namespace D3\Webauthn\Application\Controller\Admin; +use Assert\AssertionFailedException; use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnErrors; +use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use Exception; @@ -67,12 +69,17 @@ class d3webauthnadminlogin extends AdminController public function generateCredentialRequest() { - /** @var Webauthn $webauthn */ - $webauthn = oxNew(Webauthn::class); - $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions(); - Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $publicKeyCredentialRequestOptions); - $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); - $this->addTplParam('isAdmin', isAdmin()); + try { + /** @var Webauthn $webauthn */ + $webauthn = oxNew(Webauthn::class); + $userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); + $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId); + Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $publicKeyCredentialRequestOptions); + $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); + $this->addTplParam('isAdmin', isAdmin()); + } catch (WebauthnException $e) { + // ToDo write exc message to display and log + } } public function assertAuthn() @@ -92,15 +99,16 @@ class d3webauthnadminlogin extends AdminController if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) { $credential = Registry::getRequest()->getRequestEscapedParameter('credential'); $webAuthn = oxNew(Webauthn::class); + $userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); $webAuthn->assertAuthn($credential); - $user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER)); + $user->load($userId); Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, true); /** @var d3_webauthn_UserComponent $userCmp */ $loginController = oxNew(LoginController::class); return $loginController->checklogin(); } - } catch (Exception $e) { + } catch (AssertionFailedException|WebauthnException $e) { Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); $user->logout(); diff --git a/src/Application/Controller/d3_account_webauthn.php b/src/Application/Controller/d3_account_webauthn.php index c1e39e1..7b0ec89 100755 --- a/src/Application/Controller/d3_account_webauthn.php +++ b/src/Application/Controller/d3_account_webauthn.php @@ -19,6 +19,7 @@ use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\WebauthnErrors; +use D3\Webauthn\Application\Model\WebauthnException; use OxidEsales\Eshop\Application\Controller\AccountController; use OxidEsales\Eshop\Core\Registry; @@ -69,13 +70,18 @@ class d3_account_webauthn extends AccountController public function setAuthnRegister() { - $authn = oxNew(Webauthn::class); - $publicKeyCredentialCreationOptions = $authn->getCreationOptions($this->getUser()); + try { + $authn = oxNew(Webauthn::class); + $publicKeyCredentialCreationOptions = $authn->getCreationOptions($this->getUser()); + + $this->addTplParam( + 'webauthn_publickey_create', + $publicKeyCredentialCreationOptions + ); + } catch (WebauthnException $e) { + // ToDo: add exc msg to display and log + } - $this->addTplParam( - 'webauthn_publickey_create', - $publicKeyCredentialCreationOptions - ); $this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('keyname', Registry::getRequest()->getRequestEscapedParameter('credenialname')); } diff --git a/src/Application/Controller/d3webauthnlogin.php b/src/Application/Controller/d3webauthnlogin.php index 3d460a9..66a7733 100755 --- a/src/Application/Controller/d3webauthnlogin.php +++ b/src/Application/Controller/d3webauthnlogin.php @@ -15,12 +15,14 @@ namespace D3\Webauthn\Application\Controller; +use Assert\AssertionFailedException; use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\WebauthnErrors; +use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; -use Exception; +use Doctrine\DBAL\Exception as DoctrineException; use OxidEsales\Eshop\Application\Controller\FrontendController; use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; @@ -28,6 +30,8 @@ use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Utils; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; class d3webauthnlogin extends FrontendController { @@ -58,12 +62,25 @@ class d3webauthnlogin extends FrontendController return parent::render(); } + /** + * @return void + * @throws \Doctrine\DBAL\Driver\Exception + * @throws DoctrineException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ public function generateCredentialRequest() { - /** @var Webauthn $webauthn */ - $webauthn = oxNew(Webauthn::class); - $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions(); - $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); + try { + /** @var Webauthn $webauthn */ + $webauthn = oxNew(Webauthn::class); + $userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); + $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId); + $this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions); + } catch (WebauthnException $e) { + // ToDo: write exc msg to display and log + } + $this->addTplParam('isAdmin', isAdmin()); } @@ -92,7 +109,7 @@ class d3webauthnlogin extends FrontendController $userCmp->d3WebauthnRelogin($user, $credential); } - } catch (Exception $e) { + } catch (AssertionFailedException|WebauthnException $e) { Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); $user->logout(); diff --git a/src/Application/Model/Credential/PublicKeyCredential.php b/src/Application/Model/Credential/PublicKeyCredential.php index 8a941a5..4c32048 100755 --- a/src/Application/Model/Credential/PublicKeyCredential.php +++ b/src/Application/Model/Credential/PublicKeyCredential.php @@ -18,11 +18,16 @@ namespace D3\Webauthn\Application\Model\Credential; use DateTime; +use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; +use Doctrine\DBAL\Exception as DoctrineException; use Doctrine\DBAL\Query\QueryBuilder; +use Exception; use OxidEsales\Eshop\Core\Model\BaseModel; 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 Webauthn\PublicKeyCredentialSource; class PublicKeyCredential extends BaseModel @@ -84,11 +89,18 @@ class PublicKeyCredential extends BaseModel /** * @param PublicKeyCredentialSource $publicKeyCredentialSource + * @param string|null $keyName * @return void - * @throws \Exception + * @throws Exception */ public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource, string $keyName = null): void { + if ((oxNew(PublicKeyCredentialList::class)) + ->findOneByCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId()) + ) { + return; + } + // will save on every successfully assertion, set id to prevent duplicated database entries $id = $this->getIdByCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId()); @@ -104,6 +116,14 @@ class PublicKeyCredential extends BaseModel $this->save(); } + /** + * @param string $publicKeyCredentialId + * @return string|null + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ public function getIdByCredentialId(string $publicKeyCredentialId): ?string { /** @var QueryBuilder $qb */ diff --git a/src/Application/Model/Credential/PublicKeyCredentialList.php b/src/Application/Model/Credential/PublicKeyCredentialList.php index 5621a5e..b94a629 100755 --- a/src/Application/Model/Credential/PublicKeyCredentialList.php +++ b/src/Application/Model/Credential/PublicKeyCredentialList.php @@ -17,13 +17,16 @@ namespace D3\Webauthn\Application\Model\Credential; +use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; +use Doctrine\DBAL\Exception as DoctrineException; use Doctrine\DBAL\Query\QueryBuilder; use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Core\Model\ListModel; use OxidEsales\Eshop\Core\Registry; use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory; use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface; -use phpDocumentor\Reflection\Types\This; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Webauthn\PublicKeyCredentialSource; use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\PublicKeyCredentialUserEntity; @@ -37,6 +40,14 @@ class PublicKeyCredentialList extends ListModel implements PublicKeyCredentialSo parent::__construct(PublicKeyCredential::class); } + /** + * @param string $publicKeyCredentialId + * @return PublicKeyCredentialSource|null + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource { /** @var QueryBuilder $qb */ @@ -66,6 +77,14 @@ class PublicKeyCredentialList extends ListModel implements PublicKeyCredentialSo return $credential instanceof PublicKeyCredentialSource ? $credential : null; } + /** + * @param PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity + * @return array|PublicKeyCredentialSource[] + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws NotFoundExceptionInterface + */ public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array { /** @var QueryBuilder $qb */ @@ -91,7 +110,15 @@ class PublicKeyCredentialList extends ListModel implements PublicKeyCredentialSo }, $qb->execute()->fetchAllAssociative()); } - public function getAllFromUser(User $user) + /** + * @param User $user + * @return $this + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws NotFoundExceptionInterface + */ + public function getAllFromUser(User $user): PublicKeyCredentialList { if (!$user->isLoaded()) { return $this; diff --git a/src/Application/Model/Webauthn/d3PublicKeyCredentialRpEntity.php b/src/Application/Model/RelyingPartyEntity.php similarity index 66% rename from src/Application/Model/Webauthn/d3PublicKeyCredentialRpEntity.php rename to src/Application/Model/RelyingPartyEntity.php index b04c96d..bc1aef3 100755 --- a/src/Application/Model/Webauthn/d3PublicKeyCredentialRpEntity.php +++ b/src/Application/Model/RelyingPartyEntity.php @@ -17,18 +17,18 @@ declare(strict_types=1); -namespace D3\Webauthn\Application\Model\Webauthn; +namespace D3\Webauthn\Application\Model; -use OxidEsales\Eshop\Application\Model\Shop; +use OxidEsales\Eshop\Core\Registry; use Webauthn\PublicKeyCredentialRpEntity; -class d3PublicKeyCredentialRpEntity extends PublicKeyCredentialRpEntity +class RelyingPartyEntity extends PublicKeyCredentialRpEntity { - public function __construct(Shop $shop) + public function __construct() { parent::__construct( - $shop->getFieldData('oxname'), - $_SERVER['HTTP_HOST'] + Registry::getConfig()->getActiveShop()->getFieldData('oxname'), + preg_replace('/(^www\.)(.*)/mi', '$2', $_SERVER['HTTP_HOST']) ); } } \ No newline at end of file diff --git a/src/Application/Model/Webauthn/d3PublicKeyCredentialUserEntity.php b/src/Application/Model/UserEntity.php similarity index 59% rename from src/Application/Model/Webauthn/d3PublicKeyCredentialUserEntity.php rename to src/Application/Model/UserEntity.php index dd89463..01eeb8b 100755 --- a/src/Application/Model/Webauthn/d3PublicKeyCredentialUserEntity.php +++ b/src/Application/Model/UserEntity.php @@ -15,19 +15,27 @@ * @link http://www.oxidmodule.com */ -namespace D3\Webauthn\Application\Model\Webauthn; +namespace D3\Webauthn\Application\Model; use OxidEsales\Eshop\Application\Model\User; use Webauthn\PublicKeyCredentialUserEntity; -class d3PublicKeyCredentialUserEntity extends publicKeyCredentialUserEntity +class UserEntity extends publicKeyCredentialUserEntity { + /** + * @param User $user + * @throws WebauthnException + */ public function __construct(User $user) { + if (!$user->isLoaded() || !$user->getId()) { + throw oxNew(WebauthnException::class, 'can not create webauthn user entity from not loaded user'); + } + parent::__construct( - strtolower($user->getFieldData('oxfname').'.'.$user->getFieldData('oxlname')), + strtolower($user->getFieldData('oxusername')), $user->getId(), - $user->getFieldData('oxfname').', '.$user->getFieldData('oxlname') + $user->getFieldData('oxfname') . ' ' . $user->getFieldData('oxlname') ); } } \ No newline at end of file diff --git a/src/Application/Model/Webauthn.php b/src/Application/Model/Webauthn.php index 9700bf7..9ae4a8a 100644 --- a/src/Application/Model/Webauthn.php +++ b/src/Application/Model/Webauthn.php @@ -4,16 +4,21 @@ declare(strict_types=1); namespace D3\Webauthn\Application\Model; +use Assert\AssertionFailedException; use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; +use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; +use Doctrine\DBAL\Exception as DoctrineException; +use Exception; use Nyholm\Psr7\Factory\Psr17Factory; use Nyholm\Psr7Server\ServerRequestCreator; use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Core\Registry; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Webauthn\PublicKeyCredentialCreationOptions; use Webauthn\PublicKeyCredentialRequestOptions; -use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialSource; use Webauthn\Server; @@ -22,7 +27,7 @@ class Webauthn public const SESSION_CREATIONS_OPTIONS = 'd3WebAuthnCreationOptions'; public const SESSION_ASSERTION_OPTIONS = 'd3WebAuthnAssertionOptions'; - public function isAvailable() + public function isAvailable(): bool { if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' || // is HTTPS !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' || @@ -40,12 +45,16 @@ class Webauthn } /** + * @param User $user * @return false|string + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws NotFoundExceptionInterface */ public function getCreationOptions(User $user) { - /** @var d3_User_Webauthn $user */ - $userEntity = $user->d3GetWebauthnUserEntity(); + $userEntity = oxNew(UserEntity::class, $user); /** @var PublicKeyCredentialList $credentialSourceRepository */ $credentialSourceRepository = oxNew(PublicKeyCredentialList::class); @@ -66,12 +75,19 @@ class Webauthn return json_encode($publicKeyCredentialCreationOptions,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } - public function getRequestOptions() + /** + * @return false|string + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function getRequestOptions(string $userId) { /** @var d3_User_Webauthn $user */ $user = oxNew(User::class); - $user->load('oxdefaultadmin'); - $userEntity = $user->d3GetWebauthnUserEntity(); + $user->load($userId); + $userEntity = oxNew(UserEntity::class, $user); // Get the list of authenticators associated to the user $credentialList = oxNew(PublicKeyCredentialList::class); @@ -98,14 +114,10 @@ class Webauthn /** * @return Server */ - public function getServer() + public function getServer(): Server { - $rpEntity = new PublicKeyCredentialRpEntity( - Registry::getConfig()->getActiveShop()->getFieldData('oxname'), - preg_replace('/(^www\.)(.*)/mi', '$2', $_SERVER['HTTP_HOST']) - ); - - return new Server($rpEntity, oxNew(PublicKeyCredentialList::class)); + $rpEntity = oxNew(RelyingPartyEntity::class); + return oxNew(Server::class, $rpEntity, oxNew(PublicKeyCredentialList::class)); } public function saveAuthn(string $credential, string $keyName = null) @@ -128,15 +140,18 @@ class Webauthn $pkCredential = oxNew(PublicKeyCredential::class); $pkCredential->saveCredentialSource($publicKeyCredentialSource, $keyName); - } catch (\Exception $e) { - dumpvar($e->getMessage()); - dumpvar($e); - - die(); + } catch (Exception $e) { + // ToDo: write exc msg to display and log } } - public function assertAuthn(string $response) + /** + * @param string $response + * @return bool + * @throws AssertionFailedException + * @throws WebauthnException + */ + public function assertAuthn(string $response): bool { $psr17Factory = new Psr17Factory(); $creator = new ServerRequestCreator( @@ -147,10 +162,9 @@ class Webauthn ); $serverRequest = $creator->fromGlobals(); - /** @var d3_User_Webauthn $user */ $user = oxNew(User::class); - $user->load('oxdefaultadmin'); - $userEntity = $user->d3GetWebauthnUserEntity(); + $user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER)); + $userEntity = oxNew(UserEntity::class, $user); $this->getServer()->loadAndCheckAssertionResponse( html_entity_decode($response), @@ -165,6 +179,10 @@ class Webauthn /** * @param $userId * @return bool + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws NotFoundExceptionInterface */ public function isActive($userId): bool { @@ -175,15 +193,19 @@ class Webauthn /** * @param $userId * @return bool + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws DoctrineException + * @throws NotFoundExceptionInterface */ public function UserUseWebauthn($userId): bool { - /** @var d3_User_Webauthn $user */ $user = oxNew(User::class); $user->load($userId); - $entity = $user->d3GetWebauthnUserEntity(); - $credentionList = oxNew(PublicKeyCredentialList::class); - $list = $credentionList->findAllForUserEntity($entity); + $entity = oxNew(UserEntity::class, $user); + + $credentialList = oxNew(PublicKeyCredentialList::class); + $list = $credentialList->findAllForUserEntity($entity); return is_array($list) && count($list); } diff --git a/src/Application/Model/Webauthn/d3PublicKeyCredentialSource.php b/src/Application/Model/Webauthn/d3PublicKeyCredentialSource.php deleted file mode 100755 index f3f2615..0000000 --- a/src/Application/Model/Webauthn/d3PublicKeyCredentialSource.php +++ /dev/null @@ -1,76 +0,0 @@ - - * @link http://www.oxidmodule.com - */ - -namespace D3\Webauthn\Application\Model\Webauthn; - -use D3\Webauthn\Application\Model\Credential\publicKeyCredential; -use Webauthn\PublicKeyCredentialSource; - -/** @deprecated */ - -class d3PublicKeyCredentialSource extends PublicKeyCredentialSource -{ - /** - * @throws \Exception - */ - public function saveCredential() - { - $credential = oxNew(publicKeyCredential::class); - $credential->d3SetName(date('Y-m-d H:i:s')); - $credential->d3SetCredentialId($this->getPublicKeyCredentialId()); - $credential->d3SetType($this->getType()); - $credential->d3SetTransports($this->getTransports()); - $credential->d3SetAttestationType($this->getAttestationType()); - $credential->d3SetTrustPath($this->getTrustPath()); - $credential->d3SetAaguid($this->getAaguid()); - $credential->d3SetPublicKey($this->getCredentialPublicKey()); - $credential->d3SetUserHandle($this->getUserHandle()); - $credential->d3SetCounter($this->getCounter()); - - $credential->save(); - } - - public static function createFromd3PublicKeyCredential(publicKeyCredential $publicKeyCredential): self - { - return new self( - $publicKeyCredential->d3GetCredentialId(), - $publicKeyCredential->d3GetType(), - $publicKeyCredential->d3GetTransports(), - $publicKeyCredential->d3GetAttestationType(), - $publicKeyCredential->d3GetTrustPath(), - $publicKeyCredential->d3GetAaguid(), - $publicKeyCredential->d3GetPublicKey(), - $publicKeyCredential->d3GetUserHandle(), - $publicKeyCredential->d3GetCounter() - ); - } - - public static function createFromPublicKeyCredentialSource(publicKeyCredentialSource $publicKeyCredential): self - { - return new self( - $publicKeyCredential->getPublicKeyCredentialId(), - $publicKeyCredential->getType(), - $publicKeyCredential->getTransports(), - $publicKeyCredential->getAttestationType(), - $publicKeyCredential->getTrustPath(), - $publicKeyCredential->getAaguid(), - $publicKeyCredential->getCredentialPublicKey(), - $publicKeyCredential->getUserHandle(), - $publicKeyCredential->getCounter() - ); - } -} \ No newline at end of file diff --git a/src/Application/Model/Webauthn/d3PublicKeyCredentialSourceRepository.php b/src/Application/Model/Webauthn/d3PublicKeyCredentialSourceRepository.php deleted file mode 100755 index 0306c72..0000000 --- a/src/Application/Model/Webauthn/d3PublicKeyCredentialSourceRepository.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @link http://www.oxidmodule.com - */ - -/** - * @deprecated - */ - -declare(strict_types=1); - -namespace D3\Webauthn\Application\Model\Webauthn; - -use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; -use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; -use Exception; -use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; -use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; -use OxidEsales\Eshop\Core\Registry; -use Webauthn\PublicKeyCredentialSource; -use Webauthn\PublicKeyCredentialSourceRepository; -use Webauthn\PublicKeyCredentialUserEntity; - -class d3PublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepository -{ - /** - * @param string $publicKeyCredentialId - * @return PublicKeyCredentialSource|null - * @throws DatabaseConnectionException - */ - public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource - { - if (Registry::getRequest()->getRequestEscapedParameter('fnc') == 'checkregister') { - return null; - } - - $credential = oxNew(publicKeyCredential::class); - $credential->loadByCredentialId($publicKeyCredentialId); - - return $credential->getId() ? - d3PublicKeyCredentialSource::createFromd3PublicKeyCredential($credential) : - null; - } - - /** - * @param PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity - * @return array - * @throws DatabaseConnectionException - * @throws DatabaseErrorException - */ - public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array - { - $sourceList = []; - - $credentialList = oxNew(PublicKeyCredentialList::class); - $credentialList->loadAllForUserEntity($publicKeyCredentialUserEntity); - - /** @var publicKeyCredential $credential */ - foreach ($credentialList->getArray() as $credential) { - $sourceList[$credential->getId()] = d3PublicKeyCredentialSource::createFromd3PublicKeyCredential($credential); - }; - - return $sourceList; - } - - /** - * @param PublicKeyCredentialSource $publicKeyCredentialSource - * @throws Exception - */ - public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void - { - $publicKeyCredentialSource = d3PublicKeyCredentialSource::createFromPublicKeyCredentialSource($publicKeyCredentialSource); - - if ($this->findOneByCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId())) { - // increase counter - } else { - $publicKeyCredentialSource->saveCredential(); - } - } -} diff --git a/src/Application/Model/WebauthnConf.php b/src/Application/Model/WebauthnConf.php index 4d6235a..4dfd0c4 100755 --- a/src/Application/Model/WebauthnConf.php +++ b/src/Application/Model/WebauthnConf.php @@ -17,10 +17,10 @@ namespace D3\Webauthn\Application\Model; class WebauthnConf { - const WEBAUTHN_SESSION_AUTH = 'webauthn_auth'; // has valid webauthn, user is logged in completly - const WEBAUTHN_LOGIN_OBJECT = 'authnloginobject'; // webauthn register options, required for credential check - const WEBAUTHN_SESSION_CURRENTUSER = 'd3webauthnCurrentUser'; // oxid assigned to user from entered username - const WEBAUTHN_SESSION_LOGINUSER = 'd3webauthnLoginUser'; // username entered in login form - const WEBAUTHN_SESSION_CURRENTCLASS = 'd3webauthnCurrentClass'; // no usage - const WEBAUTHN_SESSION_NAVFORMPARAMS = 'd3webauthnNavFormParams'; // no usage + public const WEBAUTHN_SESSION_AUTH = 'webauthn_auth'; // has valid webauthn, user is logged in completly + public const WEBAUTHN_LOGIN_OBJECT = 'authnloginobject'; // webauthn register options, required for credential check + public const WEBAUTHN_SESSION_CURRENTUSER = 'd3webauthnCurrentUser'; // oxid assigned to user from entered username + public const WEBAUTHN_SESSION_LOGINUSER = 'd3webauthnLoginUser'; // username entered in login form + public const WEBAUTHN_SESSION_CURRENTCLASS = 'd3webauthnCurrentClass'; // no usage + public const WEBAUTHN_SESSION_NAVFORMPARAMS = 'd3webauthnNavFormParams'; // no usage } \ No newline at end of file diff --git a/src/Application/Model/WebauthnException.php b/src/Application/Model/WebauthnException.php new file mode 100644 index 0000000..435cf7d --- /dev/null +++ b/src/Application/Model/WebauthnException.php @@ -0,0 +1,10 @@ + 'Bitte mit Hardwareschlüssel authentisieren.', 'WEBAUTHN_CANCEL_LOGIN' => 'Anmeldung abbrechen', 'D3_WEBAUTHN_BREADCRUMB' => 'Passwortloses Anmelden', + 'D3_WEBAUTHN_CONF_BROWSER_REQUEST' => 'Bitte die Anfrage des Browsers bestätigen:', + 'D3_WEBAUTHN_CANCEL' => 'Abbrechen', + 'D3_WEBAUTHN_DELETE' => 'Löschen', + 'D3_WEBAUTHN_DELETE_CONFIRM' => 'Soll der Schlüssel wirklich gelöscht werden?', + 'D3_WEBAUTHN_KEYNAME' => 'Name des Schlüssels', + 'D3_WEBAUTHN_NOKEYREGISTERED' => 'kein Schlüssel registriert', 'D3_WEBAUTHN_ACCOUNT_TYPE0' => 'nur Passwort', 'D3_WEBAUTHN_ACCOUNT_TYPE1' => 'nur Auth-Stick', diff --git a/src/Application/views/admin/blocks/d3webauthn_login_admin_login_form.tpl b/src/Application/views/admin/blocks/d3webauthn_login_admin_login_form.tpl deleted file mode 100755 index 78ff1dc..0000000 --- a/src/Application/views/admin/blocks/d3webauthn_login_admin_login_form.tpl +++ /dev/null @@ -1,85 +0,0 @@ -[{if $request_webauthn}] - [{$oViewConf->getHiddenSid()}] - - - - - - [{if $Errors.default|@count}] - [{include file="inc_error.tpl" Errorlist=$Errors.default}] - [{/if}] - -
-
- [{include file=$oViewConf->getModulePath('d3webauthn', 'out/img/fingerprint.svg')}] -
-
[{oxmultilang ident="WEBAUTHN_INPUT_HELP"}]
-
- - [{* prevent cancel button (1st button) action when form is sent via Enter key *}] - - - - - [{capture name="webauthn_login"}] - function arrayToBase64String(a) { - return btoa(String.fromCharCode(...a)); - } - - function base64url2base64(input) { - input = input - .replace(/=/g, "") - .replace(/-/g, '+') - .replace(/_/g, '/'); - - const pad = input.length % 4; - if(pad) { - if(pad === 1) { - throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); - } - input += new Array(5-pad).join('='); - } - - return input; - } - - let publicKey = [{$webauthn_publickey_login}]; - - publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), function(c){return c.charCodeAt(0);}); - if (publicKey.allowCredentials) { - publicKey.allowCredentials = publicKey.allowCredentials.map(function(data) { - data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), function(c){return c.charCodeAt(0);}); - return data; - }); - } - - navigator.credentials.get({ 'publicKey': publicKey }).then(function(data){ - let publicKeyCredential = { - id: data.id, - type: data.type, - rawId: arrayToBase64String(new Uint8Array(data.rawId)), - response: { - authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), - clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), - signature: arrayToBase64String(new Uint8Array(data.response.signature)), - userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null - } - }; - document.getElementById('keyauth').value = btoa(JSON.stringify(publicKeyCredential)); - document.getElementById('login').submit(); - }) - .catch(function(error){ - // alert('Open your browser console!'); - console.log('FAIL', error); - }); - [{/capture}] - [{oxscript add=$smarty.capture.webauthn_login}] - [{oxscript}] - - [{oxstyle include=$oViewConf->getModuleUrl('d3webauthn', 'out/admin/src/css/d3webauthnlogin.css')}] - [{oxstyle}] -[{else}] - [{$smarty.block.parent}] -[{/if}] \ No newline at end of file diff --git a/src/Application/views/admin/de/d3webauthn_lang.php b/src/Application/views/admin/de/d3webauthn_lang.php index 384a90d..a3b4259 100755 --- a/src/Application/views/admin/de/d3webauthn_lang.php +++ b/src/Application/views/admin/de/d3webauthn_lang.php @@ -24,11 +24,17 @@ $aLang = [ 'D3_WEBAUTHN_ERROR_MISSINGPKC' => 'Keine prüfbaren Anfrageoptionen gespeichert. Bitte führen Sie die Anmeldung noch einmal durch bzw. wenden sich an den Betreiber.', 'WEBAUTHN_INPUT_HELP' => 'Bitte mit Hardwareschlüssel authentisieren.', 'WEBAUTHN_CANCEL_LOGIN' => 'Anmeldung abbrechen', + 'D3WEBAUTHN_CONF_BROWSER_REQUEST' => 'Bitte die Anfrage des Browsers bestätigen:', + 'D3WEBAUTHN_CANCEL' => 'Abbrechen', + 'D3WEBAUTHN_DELETE' => 'Löschen', + 'D3WEBAUTHN_DELETE_CONFIRM' => 'Soll der Schlüssel wirklich gelöscht werden?', + 'D3WEBAUTHN_CANCELNOKEYREGISTERED' => 'kein Schlüssel registriert', 'd3mxuser_webauthn' => 'Hardwareschlüssel', 'D3_WEBAUTHN_REGISTERNEW' => 'neue Registrierung erstellen', 'D3_WEBAUTHN_ADDKEY' => 'Sicherheitsschlüssel hinzufügen', + 'D3_WEBAUTHN_KEYNAME' => 'Name des Schlüssels', 'D3_WEBAUTHN_REGISTEREDKEYS' => 'registrierte Schlüssel', diff --git a/src/Application/views/admin/en/d3webauthn_lang.php b/src/Application/views/admin/en/d3webauthn_lang.php index 0158e2f..e0dc393 100755 --- a/src/Application/views/admin/en/d3webauthn_lang.php +++ b/src/Application/views/admin/en/d3webauthn_lang.php @@ -24,11 +24,17 @@ $aLang = [ 'D3_WEBAUTHN_ERROR_MISSINGPKC' => 'No verifiable request options saved. Please perform the registration again or contact the operator.', 'WEBAUTHN_INPUT_HELP' => 'Please authenticate with hardware key.', 'WEBAUTHN_CANCEL_LOGIN' => 'Cancel login', + 'D3WEBAUTHN_CONF_BROWSER_REQUEST' => 'Please confirm the browser request:', + 'D3WEBAUTHN_CANCEL' => 'Cancel', + 'D3WEBAUTHN_DELETE' => 'Delete', + 'D3WEBAUTHN_DELETE_CONFIRM' => 'Do you really want to delete the key?', + 'D3WEBAUTHN_CANCELNOKEYREGISTERED' => 'No key registered', 'd3mxuser_webauthn' => 'hardware key', 'D3_WEBAUTHN_REGISTERNEW' => 'create new registration', 'D3_WEBAUTHN_ADDKEY' => 'add security key', + 'D3_WEBAUTHN_KEYNAME' => 'Key name', 'D3_WEBAUTHN_REGISTEREDKEYS' => 'registered keys', diff --git a/src/Application/views/admin/tpl/d3user_webauthn.tpl b/src/Application/views/admin/tpl/d3user_webauthn.tpl index 8eb0efa..f3f2f66 100755 --- a/src/Application/views/admin/tpl/d3user_webauthn.tpl +++ b/src/Application/views/admin/tpl/d3user_webauthn.tpl @@ -38,7 +38,7 @@ [{capture name="javascripts"}] function deleteItem(id) { - if (confirm('wirklich loeschen?') === true) { + if (confirm('[{oxmultilang ident="D3WEBAUTHN_DELETE_CONFIRM"}]') === true) { document.getElementById('fncname').value = 'deleteKey'; document.getElementById('oxidvalue').value = id; document.getElementById('myedit').submit(); @@ -57,9 +57,9 @@

- Bitte die Anfrage Ihres Browsers bestätigen. + [{oxmultilang ident="D3WEBAUTHN_CONF_BROWSER_REQUEST"}]

- +
@@ -82,7 +82,9 @@ - +
[{oxmultilang ident=$sSaveError}] + [{oxmultilang ident=$sSaveError}] +
[{/if}] @@ -102,7 +104,9 @@ [{block name="user_d3user_totp_registerform"}] - +

@@ -132,14 +136,14 @@ [{$credential->getName()}] - delete + [{oxmultilang ident="D3WEBAUTHN_DELETE"}] [{/foreach}] [{else}]
- kein Schluessel registriert + [{oxmultilang ident="D3WEBAUTHN_CANCELNOKEYREGISTERED"}]
[{/if}] diff --git a/src/Application/views/admin/tpl/d3webauthnlogin.tpl b/src/Application/views/admin/tpl/d3webauthnlogin.tpl index cdc7d3d..b480f53 100644 --- a/src/Application/views/admin/tpl/d3webauthnlogin.tpl +++ b/src/Application/views/admin/tpl/d3webauthnlogin.tpl @@ -16,7 +16,7 @@ [{include file="js_login.tpl"}] -
+ [{block name="admin_login_form"}] [{$oViewConf->getHiddenSid()}] @@ -50,7 +50,7 @@ [{oxscript}] - + diff --git a/src/Application/views/blocks/page/shop/start_welcome_text.tpl b/src/Application/views/blocks/page/shop/start_welcome_text.tpl deleted file mode 100755 index d5a627b..0000000 --- a/src/Application/views/blocks/page/shop/start_welcome_text.tpl +++ /dev/null @@ -1,95 +0,0 @@ -[{if $webauthn_publickey_register}] - [{capture name="webauthn_register"}] - function arrayToBase64String(a) { - return btoa(String.fromCharCode(...a)); - } - - function base64url2base64(input) { - input = input - .replace(/=/g, "") - .replace(/-/g, '+') - .replace(/_/g, '/'); - - const pad = input.length % 4; - if(pad) { - if(pad === 1) { - throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); - } - input += new Array(5-pad).join('='); - } - - return input; - } - - function authnregister() { - let publicKey = [{$webauthn_publickey_register}]; - - publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), function(c){return c.charCodeAt(0);}); - publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), function(c){return c.charCodeAt(0);}); - if (publicKey.excludeCredentials) { - publicKey.excludeCredentials = publicKey.excludeCredentials.map(function(data) { - data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), function(c){return c.charCodeAt(0);}); - return data; - }); - } - - navigator.credentials.create({ 'publicKey': publicKey }) - .then(function(data){ - let publicKeyCredential = { - id: data.id, - type: data.type, - rawId: arrayToBase64String(new Uint8Array(data.rawId)), - response: { - clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), - attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject)) - } - }; - window.location = 'index.php?cl=start&fnc=checkregister&authn='+btoa(JSON.stringify(publicKeyCredential)); - }).catch(function(error){ - //alert('Open your browser console!'); - console.log('FAIL', error); - } - ); - } - [{/capture}] - [{oxscript add=$smarty.capture.webauthn_register}] - - - [{capture name="webauthn_login"}] - function authnlogin() { - let publicKey = [{$webauthn_publickey_login}]; - - publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), function(c){return c.charCodeAt(0);}); - if (publicKey.allowCredentials) { - publicKey.allowCredentials = publicKey.allowCredentials.map(function(data) { - data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), function(c){return c.charCodeAt(0);}); - return data; - }); - } - - navigator.credentials.get({ 'publicKey': publicKey }) - .then(function(data){ - let publicKeyCredential = { - id: data.id, - type: data.type, - rawId: arrayToBase64String(new Uint8Array(data.rawId)), - response: { - authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)), - clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), - signature: arrayToBase64String(new Uint8Array(data.response.signature)), - userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null - } - }; - window.location = 'index.php?cl=start&fnc=checklogin&authn='+btoa(JSON.stringify(publicKeyCredential)); - }) - .catch(function(error){ - // alert('Open your browser console!'); - console.log('FAIL', error); - }); - } - [{/capture}] - [{oxscript add=$smarty.capture.webauthn_login}] - -[{/if}] - -[{$smarty.block.parent}] \ No newline at end of file diff --git a/src/Application/views/blocks/widget/header/widget_header_servicebox_items.tpl b/src/Application/views/blocks/widget/header/widget_header_servicebox_items.tpl new file mode 100644 index 0000000..8118acd --- /dev/null +++ b/src/Application/views/blocks/widget/header/widget_header_servicebox_items.tpl @@ -0,0 +1,4 @@ +[{$smarty.block.parent}] +
  • + [{oxmultilang ident="D3_WEBAUTHN_ACCOUNT"}] +
  • \ No newline at end of file diff --git a/src/Application/views/tpl/d3_account_webauthn.tpl b/src/Application/views/tpl/d3_account_webauthn.tpl index ac43812..f9161fa 100755 --- a/src/Application/views/tpl/d3_account_webauthn.tpl +++ b/src/Application/views/tpl/d3_account_webauthn.tpl @@ -2,7 +2,7 @@ [{capture name="javascripts"}] function deleteItem(id) { - if (confirm('wirklich loeschen?') === true) { + if (confirm('[{oxmultilang ident="D3_WEBAUTHN_DELETE_CONFIRM"}]') === true) { document.getElementById('fncname').value = 'deleteKey'; document.getElementById('oxidvalue').value = id; document.getElementById('actionform').submit(); @@ -34,9 +34,9 @@

    - Bitte die Anfrage Ihres Browsers bestätigen. + [{oxmultilang ident="D3_WEBAUTHN_CONF_BROWSER_REQUEST"}]

    - +
    @@ -72,7 +72,7 @@ [{block name="user_d3user_totp_registerform"}] - +

    @@ -102,14 +102,14 @@ [{$credential->getName()}] - delete + [{oxmultilang ident="D3_WEBAUTHN_DELETE"}] [{/foreach}] [{else}]
    - kein Schluessel registriert + [{oxmultilang ident="D3_WEBAUTHN_NOKEYREGISTERED"}]
    [{/if}] diff --git a/src/Modules/Application/Component/d3_webauthn_UserComponent.php b/src/Modules/Application/Component/d3_webauthn_UserComponent.php index 41686be..4f84548 100755 --- a/src/Modules/Application/Component/d3_webauthn_UserComponent.php +++ b/src/Modules/Application/Component/d3_webauthn_UserComponent.php @@ -15,16 +15,14 @@ namespace D3\Webauthn\Modules\Application\Component; +use Assert\AssertionFailedException; use D3\Webauthn\Application\Model\WebauthnConf; -use D3\Webauthn\Application\Model\Exceptions\d3webauthnMissingPublicKeyCredentialRequestOptions; -use D3\Webauthn\Application\Model\Exceptions\d3webauthnWrongAuthException; use D3\Webauthn\Application\Model\Webauthn; -use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; -use Doctrine\DBAL\DBALException; +use D3\Webauthn\Application\Model\WebauthnException; +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\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Session; use OxidEsales\Eshop\Core\UtilsView; @@ -37,8 +35,10 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent { /** * @return string|void - * @throws DBALException - * @throws DatabaseConnectionException + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + * @throws DoctrineDriverException */ public function login_noredirect() { @@ -49,12 +49,15 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent $webauthn = $this->d3GetWebauthnObject(); if ($webauthn->isActive($userId) - && false == Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) + && !Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) ) { Registry::getSession()->setVariable( WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, $this->getParent()->getClassKey() != 'd3webauthnlogin' ? $this->getParent()->getClassKey() : 'start'); - Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $userId); + Registry::getSession()->setVariable( + WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, + $userId + ); Registry::getSession()->setVariable( WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS, $this->getParent()->getViewConfig()->getNavFormParams() @@ -67,47 +70,18 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent } parent::login_noredirect(); - - /** @var d3_User_Webauthn $user */ -/* - $oUser = $this->getUser(); - - if ($oUser && $oUser->getId()) { - $webauthn = $this->d3GetWebauthnObject(); - $webauthn->loadByUserId($oUser->getId()); - - if ($webauthn->isActive() - && false == Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) - ) { - Registry::getSession()->setVariable( - WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, - $this->getParent()->getClassKey() != 'd3webauthnlogin' ? $this->getParent()->getClassKey() : 'start'); - Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $oUser->getId()); - Registry::getSession()->setVariable( - WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS, - $this->getParent()->getViewConfig()->getNavFormParams() - ); - - $oUser->d3templogout(); - - return "d3webauthnlogin"; - } - } -*/ } /** * @return Webauthn */ - public function d3GetWebauthnObject() + public function d3GetWebauthnObject(): Webauthn { return oxNew(Webauthn::class); } /** * @return bool|string - * @throws DatabaseConnectionException - * @throws d3webauthnMissingPublicKeyCredentialRequestOptions */ public function checkWebauthnlogin() { @@ -119,15 +93,11 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent $webauthn = $this->d3GetWebauthnObject(); - try { - if (false == $this->isNoWebauthnOrNoLogin($webauthn, $userId) && $this->hasValidWebauthn($sWebauth, $webauthn)) { - $this->d3WebauthnRelogin($oUser, $sWebauth); - $this->d3WebauthnClearSessionVariables(); + if (!$this->isNoWebauthnOrNoLogin($webauthn, $userId) && $this->hasValidWebauthn($sWebauth, $webauthn)) { + $this->d3WebauthnRelogin($oUser, $sWebauth); + $this->d3WebauthnClearSessionVariables(); - return false; - } - } catch (d3webauthnWrongAuthException $oEx) { - $this->d3GetUtilsView()->addErrorToDisplay($oEx, false, false, "", 'd3webauthnlogin'); + return false; } return 'd3webauthnlogin'; @@ -136,7 +106,7 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent /** * @return UtilsView */ - public function d3GetUtilsView() + public function d3GetUtilsView(): UtilsView { return Registry::getUtilsView(); } @@ -150,9 +120,14 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent /** * @param Webauthn $webauthn + * @param $userId * @return bool + * @throws ContainerExceptionInterface + * @throws DoctrineDriverException + * @throws Exception + * @throws NotFoundExceptionInterface */ - public function isNoWebauthnOrNoLogin($webauthn, $userId) + public function isNoWebauthnOrNoLogin(Webauthn $webauthn, $userId): bool { return false == $this->d3GetSession()->getVariable("auth") || false == $webauthn->isActive($userId); @@ -162,17 +137,15 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent * @param string $sWebauth * @param Webauthn $webauthn * @return bool - * @throws d3webauthnMissingPublicKeyCredentialRequestOptions - * @throws d3webauthnWrongAuthException */ - public function hasValidWebauthn($sWebauth, $webauthn): bool + public function hasValidWebauthn(string $sWebauth, Webauthn $webauthn): bool { try { return Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) || ( $sWebauth && $webauthn->assertAuthn($sWebauth) ); - } catch (\Exception $e) { + } catch (AssertionFailedException|WebauthnException $e) { return false; } } @@ -195,19 +168,20 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent $this->d3GetSession()->deleteVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS); $this->d3GetSession()->deleteVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); $this->d3GetSession()->deleteVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS); + $this->d3GetSession()->deleteVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT); } /** * @return Session */ - public function d3GetSession() + public function d3GetSession(): Session { return Registry::getSession(); } /** * @return string|null - * @throws \Doctrine\DBAL\Driver\Exception + * @throws DoctrineDriverException * @throws Exception * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface diff --git a/src/Modules/Application/Controller/Admin/d3_LoginController_Webauthn.php b/src/Modules/Application/Controller/Admin/d3_LoginController_Webauthn.php index 1bd99c2..d09dcf6 100755 --- a/src/Modules/Application/Controller/Admin/d3_LoginController_Webauthn.php +++ b/src/Modules/Application/Controller/Admin/d3_LoginController_Webauthn.php @@ -33,8 +33,6 @@ use Psr\Container\NotFoundExceptionInterface; class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent { - - /** * @return Webauthn */ @@ -45,7 +43,10 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent /** * @return mixed|string - * @throws DatabaseConnectionException + * @throws ContainerExceptionInterface + * @throws DoctrineException + * @throws Exception + * @throws NotFoundExceptionInterface */ public function checklogin() { @@ -56,13 +57,20 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent $webauthn = $this->d3GetWebauthnObject(); if ($webauthn->isActive($userId) - && false == Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) + && !Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH) ) { Registry::getSession()->setVariable( WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, - $this->getClassKey() != 'd3webauthnadminlogin' ? $this->getClassKey() : 'admin_start'); - Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $userId); - Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER, $lgn_user); + $this->getClassKey() != 'd3webauthnadminlogin' ? $this->getClassKey() : 'admin_start' + ); + Registry::getSession()->setVariable( + WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, + $userId + ); + Registry::getSession()->setVariable( + WebauthnConf::WEBAUTHN_SESSION_LOGINUSER, + $lgn_user + ); /* Registry::getSession()->setVariable( diff --git a/src/Modules/Application/Controller/d3_StartController_Webauthn.php b/src/Modules/Application/Controller/d3_StartController_Webauthn.php deleted file mode 100755 index d6a05e0..0000000 --- a/src/Modules/Application/Controller/d3_StartController_Webauthn.php +++ /dev/null @@ -1,209 +0,0 @@ - - * @link http://www.oxidmodule.com - */ - -namespace D3\Webauthn\Modules\Application\Controller; - -use D3\Webauthn\Application\Model\Credential\d3MetadataStatementRepository; -use D3\Webauthn\Application\Model\Webauthn\d3PublicKeyCredentialRpEntity; -use D3\Webauthn\Application\Model\Webauthn\d3PublicKeyCredentialSourceRepository; -use D3\Webauthn\Application\Model\Webauthn\d3PublicKeyCredentialUserEntity; -use Nyholm\Psr7\Factory\Psr17Factory; -use Nyholm\Psr7Server\ServerRequestCreator; -use OxidEsales\Eshop\Application\Model\User; -use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; -use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; -use OxidEsales\Eshop\Core\Registry; -use Webauthn\PublicKeyCredentialCreationOptions; -use Webauthn\PublicKeyCredentialRequestOptions; -use Webauthn\Server; - -class d3_StartController_Webauthn extends d3_StartController_Webauthn_parent -{ - /** - * @return string - * @throws DatabaseConnectionException - * @throws DatabaseErrorException - */ - public function ___render() - { - if (!Registry::getRequest()->getRequestEscapedParameter('authn')) { - /*** register ***/ - $rpEntity = oxNew(d3PublicKeyCredentialRpEntity::class, Registry::getConfig()->getActiveShop()); - - $publicKeyCredentialSourceRepository = oxNew(d3PublicKeyCredentialSourceRepository::class); - - $server = new Server( - $rpEntity, - $publicKeyCredentialSourceRepository, - new d3MetadataStatementRepository() - ); - - $user = oxNew(User::class); - //$user->load('oxdefaultadmin'); - $user->load('36944b76d6e583fe2.12734046'); - - $userEntity = new d3PublicKeyCredentialUserEntity($user); - - $excludedCredentials = []; - $credentialSourceRepository = oxNew(d3PublicKeyCredentialSourceRepository::class); - foreach ($credentialSourceRepository->findAllForUserEntity($userEntity) as $credentialSource) { - $excludedCredentials[] = $credentialSource->getPublicKeyCredentialDescriptor(); - } - - $publicKeyCredentialCreationOptions = $server->generatePublicKeyCredentialCreationOptions( - $userEntity, - PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, - $excludedCredentials - ); - - $this->addTplParam( - 'webauthn_publickey_register', - json_encode($publicKeyCredentialCreationOptions, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) - ); - - if (!Registry::getSession()->isSessionStarted()) { - Registry::getSession()->start(); - } - Registry::getSession()->setVariable('authnobject', $publicKeyCredentialCreationOptions); - - /*** login ***/ - - $allowedCredentials = []; - $credentialSourceRepository = oxNew(d3PublicKeyCredentialSourceRepository::class); - foreach ($credentialSourceRepository->findAllForUserEntity($userEntity) as $credentialSource) { - $allowedCredentials[] = $credentialSource->getPublicKeyCredentialDescriptor(); - } - - // We generate the set of options. - $publicKeyCredentialRequestOptions = $server->generatePublicKeyCredentialRequestOptions( - PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED, // Default value - $allowedCredentials - ); - - $this->addTplParam( - 'webauthn_publickey_login', - json_encode($publicKeyCredentialRequestOptions, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) - ); - - Registry::getSession()->setVariable('authnloginobject', $publicKeyCredentialRequestOptions); - } - - $return = parent::render(); - - return $return; - } - - public function ____checkregister() - { - // Retrieve the PublicKeyCredentialCreationOptions object created earlier - /** @var PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions */ - $publicKeyCredentialCreationOptions = Registry::getSession()->getVariable('authnobject'); - - // Retrieve de data sent by the device - $data = base64_decode(Registry::getRequest()->getRequestParameter('authn'), true); - - $psr17Factory = new Psr17Factory(); - $creator = new ServerRequestCreator( - $psr17Factory, // ServerRequestFactory - $psr17Factory, // UriFactory - $psr17Factory, // UploadedFileFactory - $psr17Factory // StreamFactory - ); - - $serverRequest = $creator->fromGlobals(); - - /*** register ***/ - $rpEntity = oxNew(d3PublicKeyCredentialRpEntity::class, Registry::getConfig()->getActiveShop()); - - $publicKeyCredentialSourceRepository = oxNew(d3PublicKeyCredentialSourceRepository::class); - - $server = new Server( - $rpEntity, - $publicKeyCredentialSourceRepository, - new d3MetadataStatementRepository() - ); - - try { - $publicKeyCredentialSource = $server->loadAndCheckAttestationResponse( - $data, - $publicKeyCredentialCreationOptions, // The options you stored during the previous step - $serverRequest // The PSR-7 request - ); - - // The user entity and the public key credential source can now be stored using their repository - // The Public Key Credential Source repository must implement Webauthn\PublicKeyCredentialSourceRepository - $publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); - - } catch(\Exception $exception) { - dumpvar($exception); - } - dumpvar('registered'); - } - - public function _____checklogin() - { - // Retrieve the Options passed to the device - $publicKeyCredentialRequestOptions = Registry::getSession()->getVariable('authnloginobject'); - - if (!$publicKeyCredentialRequestOptions) { - return; - } - - $psr17Factory = new Psr17Factory(); - $creator = new ServerRequestCreator( - $psr17Factory, // ServerRequestFactory - $psr17Factory, // UriFactory - $psr17Factory, // UploadedFileFactory - $psr17Factory // StreamFactory - ); - - $serverRequest = $creator->fromGlobals(); - - // Retrieve de data sent by the device - $data = base64_decode(Registry::getRequest()->getRequestParameter('authn')); - - $publicKeyCredentialSourceRepository = oxNew(d3PublicKeyCredentialSourceRepository::class); - - $server = new Server( - new d3PublicKeyCredentialRpEntity(Registry::getConfig()->getActiveShop()), - $publicKeyCredentialSourceRepository, - new d3MetadataStatementRepository() - ); - - $user = oxNew(User::class); - //$user->load('oxdefaultadmin'); - $user->load('36944b76d6e583fe2.12734046'); - - $userEntity = new d3PublicKeyCredentialUserEntity($user); - - try { - $publicKeyCredentialSource = $server->loadAndCheckAssertionResponse( - $data, - $publicKeyCredentialRequestOptions, // The options you stored during the previous step - $userEntity, // The user entity - $serverRequest // The PSR-7 request - ); - - //If everything is fine, this means the user has correctly been authenticated using the - // authenticator defined in $publicKeyCredentialSource - } catch(\Throwable $exception) { - dumpvar(openssl_error_string()); - dumpvar($exception); - } - - dumpvar('logged in'); - - } -} \ No newline at end of file diff --git a/src/Modules/Application/Model/d3_User_Webauthn.php b/src/Modules/Application/Model/d3_User_Webauthn.php index 1baac67..1ef0f6a 100755 --- a/src/Modules/Application/Model/d3_User_Webauthn.php +++ b/src/Modules/Application/Model/d3_User_Webauthn.php @@ -16,10 +16,8 @@ namespace D3\Webauthn\Modules\Application\Model; use D3\Webauthn\Application\Model\WebauthnConf; -use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Registry; use ReflectionClass; -use Webauthn\PublicKeyCredentialUserEntity; class d3_User_Webauthn extends d3_User_Webauthn_parent { @@ -58,22 +56,6 @@ class d3_User_Webauthn extends d3_User_Webauthn_parent return $return; } - /** - * @return PublicKeyCredentialUserEntity - */ - public function d3GetWebauthnUserEntity(): PublicKeyCredentialUserEntity - { - if ($this->isLoaded()) { - return oxNew(PublicKeyCredentialUserEntity::class, - $this->getFieldData('oxusername'), - $this->getId(), - $this->getFieldData('oxfname') . ' ' . $this->getFieldData('oxlname') - ); - } - - throw oxNew(StandardException::class, 'can not create webauthn user entity from not loaded user'); - } - public function login($userName, $password, $setSessionCookie = false) { if (Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) { diff --git a/src/metadata.php b/src/metadata.php index 3baa2c1..9bce957 100755 --- a/src/metadata.php +++ b/src/metadata.php @@ -25,19 +25,15 @@ use D3\Webauthn\Application\Controller\d3_account_webauthn; use D3\Webauthn\Application\Controller\d3webauthnlogin; use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent; use D3\Webauthn\Modules\Application\Controller\Admin\d3_LoginController_Webauthn; -use D3\Webauthn\Modules\Application\Controller\d3_StartController_Webauthn; use D3\Webauthn\Modules\Application\Controller\d3_webauthn_OrderController; use D3\Webauthn\Modules\Application\Controller\d3_webauthn_PaymentController; use D3\Webauthn\Modules\Application\Controller\d3_webauthn_UserController; use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use D3\Webauthn\Modules\Core\d3_webauthn_utils; -use D3\Webauthn\Setup as ModuleSetup; -use D3\ModCfg\Application\Model\d3utils; 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\StartController; use OxidEsales\Eshop\Application\Controller\UserController; use OxidEsales\Eshop\Core\Utils; use OxidEsales\Eshop\Application\Model as OxidModel; @@ -69,7 +65,6 @@ $aModule = array( PaymentController::class => d3_webauthn_PaymentController::class, OrderController::class => d3_webauthn_OrderController::class, OxidModel\User::class => d3_User_Webauthn::class, - StartController::class => d3_StartController_Webauthn::class, LoginController::class => d3_LoginController_Webauthn::class, Utils::class => d3_webauthn_utils::class, UserComponent::class => d3_webauthn_UserComponent::class, @@ -99,15 +94,10 @@ $aModule = array( 'block' => 'account_menu', 'file' => 'Application/views/blocks/page/account/inc/account_menu.tpl', ], - [ - 'template' => 'page/shop/start.tpl', - 'block' => 'start_welcome_text', - 'file' => 'Application/views/blocks/page/shop/start_welcome_text.tpl', - ], [ - 'template' => 'login.tpl', - 'block' => 'admin_login_form', - 'file' => 'Application/views/admin/blocks/d3webauthn_login_admin_login_form.tpl', + 'template' => 'widget/header/servicebox.tpl', + 'block' => 'widget_header_servicebox_items', + 'file' => 'Application/views/blocks/widget/header/widget_header_servicebox_items.tpl', ] ] ); \ No newline at end of file