improve error handling

This commit is contained in:
Daniel Seifert 2022-11-03 13:18:02 +01:00
parent 925d55cb01
commit 8df85439e4
Signed by: DanielS
GPG Key ID: 8A7C4C6ED1915C6F
14 changed files with 229 additions and 97 deletions

View File

@ -17,9 +17,9 @@ namespace D3\Webauthn\Application\Controller\Admin;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Exceptions\WebauthnCreateException;
use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\Webauthn;
use D3\Webauthn\Application\Model\WebauthnConf;
use D3\Webauthn\Application\Model\WebauthnErrors;
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\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException; use Doctrine\DBAL\Exception as DoctrineException;
@ -71,8 +71,8 @@ class d3user_webauthn extends AdminDetailsController
$this->setPageType( 'requestnew' ); $this->setPageType( 'requestnew' );
$this->setAuthnRegister(); $this->setAuthnRegister();
} catch (Exception|ContainerExceptionInterface|NotFoundExceptionInterface|DoctrineDriverException $e) { } catch (Exception|ContainerExceptionInterface|NotFoundExceptionInterface|DoctrineDriverException $e) {
Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); Registry::getUtilsView()->addErrorToDisplay($e);
Registry::getLogger()->error('webauthn creation request: '.$e->getMessage()); Registry::getLogger()->error('webauthn creation request: '.$e->getMessage(), ['UserId' => $this->getEditObjectId()]);
Registry::getUtils()->redirect('index.php?cl=d3user_webauthn'); Registry::getUtils()->redirect('index.php?cl=d3user_webauthn');
} }
} }
@ -81,8 +81,9 @@ class d3user_webauthn extends AdminDetailsController
{ {
try { try {
if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'error' ) ) ) { if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'error' ) ) ) {
$errors = oxNew( WebauthnErrors::class ); /** @var WebauthnCreateException $e */
Registry::getUtilsView()->addErrorToDisplay( $errors->translateError( Registry::getRequest()->getRequestEscapedParameter( 'error' ), WebauthnConf::TYPE_CREATE ) ); $e = oxNew(WebauthnCreateException::class, Registry::getRequest()->getRequestEscapedParameter( 'error' ));
throw $e;
} }
if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'credential' ) ) ) { if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'credential' ) ) ) {
@ -90,8 +91,9 @@ class d3user_webauthn extends AdminDetailsController
$webauthn = oxNew( Webauthn::class ); $webauthn = oxNew( Webauthn::class );
$webauthn->saveAuthn( Registry::getRequest()->getRequestEscapedParameter( 'credential' ), Registry::getRequest()->getRequestEscapedParameter( 'keyname' ) ); $webauthn->saveAuthn( Registry::getRequest()->getRequestEscapedParameter( 'credential' ), Registry::getRequest()->getRequestEscapedParameter( 'keyname' ) );
} }
} catch (Exception|NotFoundExceptionInterface|ContainerExceptionInterface|DoctrineDriverException $e) { } catch (WebauthnException|Exception|NotFoundExceptionInterface|ContainerExceptionInterface|DoctrineDriverException $e) {
Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); Registry::getLogger()->error($e->getDetailedErrorMessage(), ['UserId' => $this->getEditObjectId()]);
Registry::getUtilsView()->addErrorToDisplay($e);
} }
} }

View File

@ -16,10 +16,10 @@
namespace D3\Webauthn\Application\Controller\Admin; namespace D3\Webauthn\Application\Controller\Admin;
use Assert\AssertionFailedException; use Assert\AssertionFailedException;
use D3\Webauthn\Application\Model\Exceptions\WebauthnGetException;
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\Application\Model\WebauthnErrors; use D3\Webauthn\Application\Model\Exceptions\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\Driver\Exception as DoctrineDriverException;
@ -28,7 +28,6 @@ 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\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\ContainerExceptionInterface;
@ -77,19 +76,18 @@ class d3webauthnadminlogin extends AdminController
*/ */
public function generateCredentialRequest() public function generateCredentialRequest()
{ {
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
try { try {
/** @var Webauthn $webauthn */ /** @var Webauthn $webauthn */
$webauthn = oxNew(Webauthn::class); $webauthn = oxNew(Webauthn::class);
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
$publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId); $publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $publicKeyCredentialRequestOptions); Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $publicKeyCredentialRequestOptions);
$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) {
Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true); Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED')); Registry::getUtilsView()->addErrorToDisplay($e);
Registry::getUtilsView()->addErrorToDisplay($exception); Registry::getLogger()->error('webauthn request options: '.$e->getDetailedErrorMessage(), ['UserId' => $userId]);
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
$this->getUtils()->redirect('index.php?cl=login'); $this->getUtils()->redirect('index.php?cl=login');
} }
} }
@ -98,21 +96,22 @@ class d3webauthnadminlogin extends AdminController
{ {
/** @var d3_User_Webauthn $user */ /** @var d3_User_Webauthn $user */
$user = oxNew(User::class); $user = oxNew(User::class);
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
try { try {
if (strlen(Registry::getRequest()->getRequestEscapedParameter('error'))) { if (strlen(Registry::getRequest()->getRequestEscapedParameter('error'))) {
$errors = oxNew(WebauthnErrors::class); /** @var WebauthnGetException $e */
throw oxNew( $e = oxNew(
WebauthnException::class, WebauthnGetException::class,
$errors->translateError(Registry::getRequest()->getRequestEscapedParameter('error'), WebauthnConf::TYPE_GET) Registry::getRequest()->getRequestEscapedParameter('error')
); );
throw $e;
} }
if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) { if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) {
$credential = Registry::getRequest()->getRequestEscapedParameter('credential'); $credential = Registry::getRequest()->getRequestEscapedParameter('credential');
$webAuthn = oxNew(Webauthn::class); $webAuthn = oxNew( Webauthn::class );
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); $webAuthn->assertAuthn( $credential );
$webAuthn->assertAuthn($credential);
$user->load($userId); $user->load($userId);
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, true); Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, true);
@ -120,11 +119,9 @@ class d3webauthnadminlogin extends AdminController
$loginController = oxNew(LoginController::class); $loginController = oxNew(LoginController::class);
return $loginController->checklogin(); return $loginController->checklogin();
} }
} catch (AssertionFailedException|WebauthnException $e) { } catch (WebauthnException $e) {
Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); Registry::getUtilsView()->addErrorToDisplay($e);
// ToDo: add requested username Registry::getLogger()->error('Webauthn: '.$e->getDetailedErrorMessage(), ['UserId' => $userId]);
Registry::getLogger()->info($e->getMessage());
$user->logout(); $user->logout();
$this->getUtils()->redirect('index.php?cl=login'); $this->getUtils()->redirect('index.php?cl=login');
} }

View File

@ -18,12 +18,17 @@ namespace D3\Webauthn\Application\Controller;
use D3\Webauthn\Application\Controller\Traits\accountTrait; use D3\Webauthn\Application\Controller\Traits\accountTrait;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Exceptions\WebauthnCreateException;
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\Application\Model\WebauthnErrors; use D3\Webauthn\Application\Model\WebauthnErrors;
use D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException;
use OxidEsales\Eshop\Application\Controller\AccountController; use OxidEsales\Eshop\Application\Controller\AccountController;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class d3_account_webauthn extends AccountController class d3_account_webauthn extends AccountController
{ {
@ -61,10 +66,21 @@ class d3_account_webauthn extends AccountController
return $credentialList->getAllFromUser($oUser); return $credentialList->getAllFromUser($oUser);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws DoctrineDriverException
* @throws DoctrineException
*/
public function requestNewCredential() public function requestNewCredential()
{ {
$this->setPageType('requestnew'); try {
$this->setAuthnRegister(); $this->setAuthnRegister();
$this->setPageType('requestnew');
} catch (WebauthnException $e) {
Registry::getLogger()->error('webauthn register: '.$e->getDetailedErrorMessage(), ['UserId: ' => $this->getUser()->getId()]);
Registry::getUtilsView()->addErrorToDisplay($e);
}
} }
public function setPageType($pageType) public function setPageType($pageType)
@ -72,19 +88,22 @@ class d3_account_webauthn extends AccountController
$this->addTplParam('pageType', $pageType); $this->addTplParam('pageType', $pageType);
} }
/**
* @throws WebauthnException
* @throws DoctrineDriverException
* @throws DoctrineException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function setAuthnRegister() public function setAuthnRegister()
{ {
try { $authn = oxNew(Webauthn::class);
$authn = oxNew(Webauthn::class); $publicKeyCredentialCreationOptions = $authn->getCreationOptions($this->getUser());
$publicKeyCredentialCreationOptions = $authn->getCreationOptions($this->getUser());
$this->addTplParam( $this->addTplParam(
'webauthn_publickey_create', 'webauthn_publickey_create',
$publicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions
); );
} catch (WebauthnException $e) {
// ToDo: add exc msg to display and log
}
$this->addTplParam('isAdmin', isAdmin()); $this->addTplParam('isAdmin', isAdmin());
$this->addTplParam('keyname', Registry::getRequest()->getRequestEscapedParameter('credenialname')); $this->addTplParam('keyname', Registry::getRequest()->getRequestEscapedParameter('credenialname'));
@ -92,20 +111,20 @@ class d3_account_webauthn extends AccountController
public function saveAuthn() public function saveAuthn()
{ {
if (strlen(Registry::getRequest()->getRequestEscapedParameter('error'))) { try {
$errors = oxNew(WebauthnErrors::class); if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'error' ) ) ) {
Registry::getUtilsView()->addErrorToDisplay( /** @var WebauthnCreateException $e */
$errors->translateError(Registry::getRequest()->getRequestEscapedParameter('error'), WebauthnConf::TYPE_CREATE) $e = oxNew( WebauthnCreateException::class, Registry::getRequest()->getRequestEscapedParameter( 'error' ) );
); throw $e;
} }
if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) { if ( strlen( Registry::getRequest()->getRequestEscapedParameter( 'credential' ) ) ) {
/** @var Webauthn $webauthn */ /** @var Webauthn $webauthn */
$webauthn = oxNew(Webauthn::class); $webauthn = oxNew( Webauthn::class );
$webauthn->saveAuthn( $webauthn->saveAuthn( Registry::getRequest()->getRequestEscapedParameter( 'credential' ), Registry::getRequest()->getRequestEscapedParameter( 'keyname' ) );
Registry::getRequest()->getRequestEscapedParameter('credential'), }
Registry::getRequest()->getRequestEscapedParameter('keyname') } catch (WebauthnException $e) {
); Registry::getUtilsView()->addErrorToDisplay( $e );
} }
} }

View File

@ -17,7 +17,7 @@ namespace D3\Webauthn\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 D3\Webauthn\Application\Model\WebauthnException; use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; 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;
@ -78,17 +78,17 @@ class d3webauthnlogin extends FrontendController
*/ */
public function generateCredentialRequest() public function generateCredentialRequest()
{ {
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
try { try {
/** @var Webauthn $webauthn */ /** @var Webauthn $webauthn */
$webauthn = oxNew(Webauthn::class); $webauthn = oxNew(Webauthn::class);
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
$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) {
Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true); Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED')); Registry::getLogger()->error('webauthn request options: '.$e->getDetailedErrorMessage(), ['UserId' => $userId]);
Registry::getUtilsView()->addErrorToDisplay($exception); Registry::getUtilsView()->addErrorToDisplay($e);
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
$this->getUtils()->redirect('index.php?cl=start'); $this->getUtils()->redirect('index.php?cl=start');
} }

View File

@ -0,0 +1,26 @@
<?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\Application\Model\Exceptions;
use D3\Webauthn\Application\Model\WebauthnConf;
class WebauthnCreateException extends WebauthnException
{
public function getRequestType(): string
{
return WebauthnConf::TYPE_CREATE;
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace D3\Webauthn\Application\Model\Exceptions;
use D3\Webauthn\Application\Model\WebauthnErrors;
use OxidEsales\Eshop\Core\Exception\StandardException;
class WebauthnException extends StandardException
{
public $detailedErrorMessage = null;
public function __construct( $sMessage = "not set", $iCode = 0, \Exception $previous = null )
{
$this->setDetailedErrorMessage($sMessage);
parent::__construct(
(oxNew(WebauthnErrors::class))->translateError($sMessage, $this->getRequestType()),
$iCode,
$previous
);
}
/**
* @return string|null
*/
public function getRequestType(): ?string
{
return null;
}
/**
* @return null|string
*/
public function getDetailedErrorMessage(): ?string
{
return $this->detailedErrorMessage;
}
/**
* @param string|null $detailedErrorMessage
*/
public function setDetailedErrorMessage(string $detailedErrorMessage = null): void
{
$this->detailedErrorMessage = $detailedErrorMessage;
}
}

View File

@ -0,0 +1,26 @@
<?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\Application\Model\Exceptions;
use D3\Webauthn\Application\Model\WebauthnConf;
class WebauthnGetException extends WebauthnException
{
public function getRequestType(): string
{
return WebauthnConf::TYPE_GET;
}
}

View File

@ -17,10 +17,11 @@
namespace D3\Webauthn\Application\Model; namespace D3\Webauthn\Application\Model;
use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
use Webauthn\PublicKeyCredentialUserEntity; use Webauthn\PublicKeyCredentialUserEntity;
class UserEntity extends publicKeyCredentialUserEntity class UserEntity extends PublicKeyCredentialUserEntity
{ {
/** /**
* @param User $user * @param User $user
@ -29,7 +30,9 @@ class UserEntity extends publicKeyCredentialUserEntity
public function __construct(User $user) public function __construct(User $user)
{ {
if (!$user->isLoaded() || !$user->getId()) { if (!$user->isLoaded() || !$user->getId()) {
throw oxNew(WebauthnException::class, 'can not create webauthn user entity from not loaded user'); /** @var WebauthnException $e */
$e = oxNew(WebauthnException::class, 'can not create webauthn user entity from not loaded user');
throw $e;
} }
parent::__construct( parent::__construct(

View File

@ -7,6 +7,8 @@ namespace D3\Webauthn\Application\Model;
use Assert\AssertionFailedException; use Assert\AssertionFailedException;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredential; use D3\Webauthn\Application\Model\Credential\PublicKeyCredential;
use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList; use D3\Webauthn\Application\Model\Credential\PublicKeyCredentialList;
use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use D3\Webauthn\Application\Model\Exceptions\WebauthnGetException;
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\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception as DoctrineException; use Doctrine\DBAL\Exception as DoctrineException;
@ -37,9 +39,8 @@ class Webauthn
return true; return true;
} }
Registry::getUtilsView()->addErrorToDisplay( $e = oxNew(WebauthnException::class, 'D3_WEBAUTHN_ERR_UNSECURECONNECTION');
Registry::getLang()->translateString('D3_WEBAUTHN_ERR_UNSECURECONNECTION', null, true) Registry::getUtilsView()->addErrorToDisplay($e);
);
return false; return false;
} }
@ -51,6 +52,7 @@ class Webauthn
* @throws DoctrineDriverException * @throws DoctrineDriverException
* @throws DoctrineException * @throws DoctrineException
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
* @throws WebauthnException
*/ */
public function getCreationOptions(User $user) public function getCreationOptions(User $user)
{ {
@ -81,6 +83,7 @@ class Webauthn
* @throws DoctrineException * @throws DoctrineException
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
* @throws WebauthnException
*/ */
public function getRequestOptions(string $userId) public function getRequestOptions(string $userId)
{ {
@ -157,6 +160,7 @@ class Webauthn
* @param string $response * @param string $response
* *
* @return bool * @return bool
* @throws WebauthnException
*/ */
public function assertAuthn(string $response): bool public function assertAuthn(string $response): bool
{ {
@ -173,12 +177,13 @@ class Webauthn
$user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER)); $user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER));
$userEntity = oxNew(UserEntity::class, $user); $userEntity = oxNew(UserEntity::class, $user);
$this->getServer()->loadAndCheckAssertionResponse( try {
html_entity_decode($response), $this->getServer()->loadAndCheckAssertionResponse( html_entity_decode( $response ), Registry::getSession()->getVariable( self::SESSION_ASSERTION_OPTIONS ), $userEntity, $serverRequest );
Registry::getSession()->getVariable(self::SESSION_ASSERTION_OPTIONS), } catch (AssertionFailedException $e) {
$userEntity, /** @var WebauthnGetException $exc */
$serverRequest $exc = oxNew(WebauthnGetException::class, $e->getMessage(), 0, $e);
); throw $exc;
}
return true; return true;
} }

View File

@ -1,10 +0,0 @@
<?php
namespace D3\Webauthn\Application\Model;
use OxidEsales\Eshop\Core\Exception\StandardException;
class WebauthnException extends StandardException
{
}

View File

@ -10,6 +10,7 @@ $aLang = array(
'PAGE_TITLE_D3WEBAUTHNLOGIN' => 'Passwortloses Anmelden', 'PAGE_TITLE_D3WEBAUTHNLOGIN' => 'Passwortloses Anmelden',
'D3_WEBAUTHN_ACCOUNT' => 'Meine Schlüssel', 'D3_WEBAUTHN_ACCOUNT' => 'Meine Schlüssel',
'PAGE_TITLE_D3_ACCOUNT_WEBAUTHN' => 'Meine Schlüssel',
'D3_WEBAUTHN_ACCOUNT_DESC' => 'Verwalten Sie hier Ihre Anmeldeschlüssel.', 'D3_WEBAUTHN_ACCOUNT_DESC' => 'Verwalten Sie hier Ihre Anmeldeschlüssel.',
'D3_WEBAUTHN_ACC_REGISTERNEW' => 'neue Registrierung erstellen', 'D3_WEBAUTHN_ACC_REGISTERNEW' => 'neue Registrierung erstellen',
'D3_WEBAUTHN_ACC_ADDKEY' => 'Sicherheitsschlüssel hinzufügen', 'D3_WEBAUTHN_ACC_ADDKEY' => 'Sicherheitsschlüssel hinzufügen',
@ -32,5 +33,6 @@ $aLang = array(
'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_UNSECURECONNECTION' => 'Die Verwendung von Sicherheitsschlüsseln ist nur bei lokalen oder gesicherten Verbindungen (https) möglich.',
'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.', '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

@ -52,4 +52,12 @@ $aLang = [
'D3_WEBAUTHN_ERR_TECHNICALERROR' => 'Beim Prüfen der Zugangsdaten ist ein technischer Fehler aufgetreten.', 'D3_WEBAUTHN_ERR_TECHNICALERROR' => 'Beim Prüfen der Zugangsdaten ist ein technischer Fehler aufgetreten.',
'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.', '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.',
'SHOP_MODULE_GROUP_d3webauthn_general' => 'Grundeinstellungen',
'SHOP_MODULE_d3webauthn_diffshopurl' => 'abweichende Shop-URL',
'HELP_SHOP_MODULE_d3webauthn_diffshopurl' => '<p>Die Zugangsdaten werden für die URL Ihres Shops festgeschrieben. Dazu wird bei jeder Anfrage die Domain Ihres Shops ohne "http(s)://" und ohne "www." übergeben.</p>'.
'<p>Ist Ihr Shop unter verschiedenen Subdomains erreichbar, können Sie hier die Hauptdomain angeben, die zur Registrierung verwendet werden soll. Beachten Sie bitte, '.
'dass die hier angegebene Adresse mit der des Shopaufrufs übereinstimmen muss. Shopfremde Adressen werden bei der Verwendung abgelehnt.</p>'.
'<p>Bleibt das Feld leer, wird die Adresse des aktuellen Shopaufrufs verwendet. Bei Verwendung unterschiedlicher Adressen muss vom Nutzer für jede Adresse eine separate '.
'Schlüsselregistrierung durchgeführt werden.</p>'
]; ];

View File

@ -52,4 +52,13 @@ $aLang = [
'D3_WEBAUTHN_ERR_TECHNICALERROR' => 'A technical error occurred while checking the access data.', 'D3_WEBAUTHN_ERR_TECHNICALERROR' => 'A technical error occurred while checking the access data.',
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Unfortunately, logging in with a security key is currently not possible for technical reasons. Please use your password instead.', 'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Unfortunately, logging in with a security key is currently not possible for technical reasons. Please use your password instead.',
'SHOP_MODULE_GROUP_d3webauthn_general' => 'Basic settings',
'SHOP_MODULE_d3webauthn_diffshopurl' => 'different shop URL',
'HELP_SHOP_MODULE_d3webauthn_diffshopurl' => '<p>The access data are fixed for the URL of your shop. For this purpose, the domain of your shop without "http(s)://" and without "www." '.
'is transferred with every request.</p>'.
'<p>If your shop can be reached under different subdomains, you can enter the main domain here that is to be used for registration. Please '.
'note that the address given here must match the address of the shop call. Addresses that do not match the shop will be rejected.</p>'.
'<p>If the field remains empty, the address of the current shop call is used. If different addresses are used, a separate key registration '.
'must be carried out by the user for each address.</p>'
]; ];

View File

@ -16,20 +16,17 @@
namespace D3\Webauthn\Modules\Application\Component; namespace D3\Webauthn\Modules\Application\Component;
use Assert\AssertionFailedException; use Assert\AssertionFailedException;
use D3\Webauthn\Application\Model\Exceptions\WebauthnGetException;
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\WebauthnErrors; use D3\Webauthn\Application\Model\Exceptions\WebauthnException;
use D3\Webauthn\Application\Model\WebauthnException;
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\Driver\Exception as DoctrineDriverException;
use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder;
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 OxidEsales\Eshop\Core\UtilsView; 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\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
@ -130,7 +127,7 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
( (
$sWebauth && $webauthn->assertAuthn($sWebauth) $sWebauth && $webauthn->assertAuthn($sWebauth)
); );
} catch (AssertionFailedException|WebauthnException $e) { } catch (WebauthnException $e) {
return false; return false;
} }
} }
@ -184,26 +181,27 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
try { try {
if (strlen(Registry::getRequest()->getRequestEscapedParameter('error'))) { if (strlen(Registry::getRequest()->getRequestEscapedParameter('error'))) {
$errors = oxNew(WebauthnErrors::class); /** @var WebauthnGetException $e */
throw oxNew( $e = oxNew(
WebauthnException::class, WebauthnGetException::class,
$errors->translateError(Registry::getRequest()->getRequestEscapedParameter('error'), WebauthnConf::TYPE_GET) Registry::getRequest()->getRequestEscapedParameter('error')
); );
throw $e;
} }
if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) { if (strlen(Registry::getRequest()->getRequestEscapedParameter('credential'))) {
$credential = Registry::getRequest()->getRequestEscapedParameter('credential'); $credential = Registry::getRequest()->getRequestEscapedParameter('credential');
$webAuthn = oxNew(Webauthn::class); $webAuthn = oxNew( Webauthn::class );
$webAuthn->assertAuthn($credential); $webAuthn->assertAuthn( $credential );
$user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER)); $user->load(Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER));
$this->d3WebauthnRelogin($user, $credential); $this->d3WebauthnRelogin($user, $credential);
} }
} catch (WebauthnException $e) {
} catch (AssertionFailedException|WebauthnException $e) { Registry::getUtilsView()->addErrorToDisplay($e);
Registry::getUtilsView()->addErrorToDisplay($e->getMessage()); Registry::getLogger()->error(
// ToDo: add requested username 'Webauthn: '.$e->getDetailedErrorMessage(),
Registry::getLogger()->info($e->getMessage()); ['UserId' => Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER)]
);
$user->logout(); $user->logout();
Registry::getUtils()->redirect('index.php?cl=start'); Registry::getUtils()->redirect('index.php?cl=start');
} }