Compare commits

...

17 Commits

Author SHA1 Message Date
Daniel Seifert bb594eb3c9
adjust documentation 2022-09-30 11:23:09 +02:00
Daniel Seifert 5b6dd4a4da
Merge remote-tracking branch 'remotes/GH/master' into rel_1.x
# Conflicts:
#	src/Modules/Core/d3_totp_utils.php
2022-09-26 15:03:42 +02:00
gitea Admin Panel cdff7abe01
Merge pull request #2 from tmloberon/tmloberon-force-2fa
Require administrators to activate 2FA.
2022-09-26 15:01:29 +02:00
Daniel Seifert 6b9130fc79
change OXID shop dependency from CE metapackage to core package 2022-09-26 14:58:44 +02:00
Daniel Seifert 87e18c90a1
Merge remote-tracking branch 'remotes/GH/master' into rel_1.x
# Conflicts:
#	composer.json
2022-09-26 14:55:09 +02:00
gitea Admin Panel f0a3124303
Merge pull request #1 from tmloberon/tmloberon-new-bacon-version
Update composer
2022-09-26 14:50:39 +02:00
Daniel Seifert 26f5b6b460
list example TOTP apps for Android and Apple devices 2022-09-26 14:40:33 +02:00
Tobias Matthaiou d3576c2dd7 Require administrators to activate 2FA. 2022-09-13 17:06:27 +02:00
Tobias Matthaiou 96f6de6300 The module is now compatible with all:
- bacon/bacon-qr-code: ^1.0 || ^2.0
- oxid-esales/oxideshop-metapackage-ce: "~6.0.3 || ~6.1.0 || ~6.2.0 || ~6.3.0  || ~6.4.0  || ~6.5.0"
2022-09-12 17:16:53 +02:00
Tobias Matthaiou 219427fb75
Autor und neuste version bacon/bacon-qr-code 2022-09-12 15:07:42 +02:00
gitea Admin Panel 6e72394bc7
Update README.md 2020-12-22 09:33:59 +01:00
gitea Admin Panel 4b4176cc7b
Create README.md 2020-12-22 09:33:38 +01:00
Daniel Seifert 9bef2d93e7
change module title logo (D3) source to external asset 2020-06-16 10:10:59 +02:00
Daniel Seifert fa34a5b762
fix non https url in composer.json 2020-06-08 10:15:40 +02:00
Daniel Seifert 3816d0fa35
change line endings for easy patching 2020-05-25 10:26:00 +02:00
Daniel Seifert 86cd851e1e change typographical dashs to default one 2020-01-09 08:50:44 +01:00
Daniel Seifert 6bb22efefd add modcfg suggestion 2019-11-08 09:39:01 +01:00
18 changed files with 430 additions and 223 deletions

BIN
.gitattributes vendored Normal file

Binary file not shown.

12
README.md Normal file
View File

@ -0,0 +1,12 @@
# oxtotp (2FA)
Modul für eine 2-Faktor-Authentisierung (2FA) zum Login in Front- und Backend zusätzlich zu Benutzername und Passwort.
- Authentisierung wird nur bei Benutzerkonten gezeigt, die dieses aktiviert haben - sonst nur Standardanmeldung die Basis der Passwortgenerierung wird fĂĽr jedes Benutzerkonto individuell angelegt</li>
- Einrichtung des Zugangs in der Auth-App kann durch scanbaren QR-Code oder kopierbare Zeichenkette erfolgen
- Validierung der Einmalpassworte und Generierung der QR-Codes werden ausschließlich innerhalb des Shops durchgeführt - keine Kommunikation nach außen nötig
- statische Backupcodes ermöglichen auch eine (begrenzte) Anmeldung ohne Zugang zum Generierungstool
- optionale Verpflichtung zur 2FA-Nutzung fĂĽr Adminuser

View File

@ -1,45 +1,55 @@
{
"name": "d3/oxtotp",
"description": "Two-factor authentication via time-based one-time password for OXID eSales shop",
"type": "oxideshop-module",
"keywords": [
"oxid",
"modules",
"eShop",
"d3",
"2FA"
],
"authors": [
{
"name": "D3 Data Development (Inh. Thomas Dartsch)",
"email": "info@shopmodule.com",
"homepage": "http://www.d3data.de",
"role": "Owner"
}
],
"support": {
"email": "support@shopmodule.com"
},
"homepage": "https://www.oxidmodule.com/",
"license": [
"GPL-3.0-only"
],
"extra": {
"oxideshop": {
"source-directory": "/src",
"target-directory": "d3/totp"
}
},
"require": {
"php": ">=5.6",
"oxid-esales/oxideshop-metapackage-ce": "~6.0.3 || ~6.1.0 || ~6.2.0",
"spomky-labs/otphp": "^8.3",
"bacon/bacon-qr-code": "^1.0",
"zendframework/zend-math": "^3.2"
},
"autoload": {
"psr-4": {
"D3\\Totp\\": "../../../source/modules/d3/totp"
}
}
}
{
"name": "d3/oxtotp",
"description": "Two-factor authentication via time-based one-time password for OXID eSales shop",
"type": "oxideshop-module",
"keywords": [
"oxid",
"modules",
"eShop",
"d3",
"2FA"
],
"authors": [
{
"name": "D3 Data Development (Inh. Thomas Dartsch)",
"email": "info@shopmodule.com",
"homepage": "https://www.d3data.de",
"role": "Owner"
},
{
"name": "Tobi Matthaiou",
"email": "tm@loberon.com",
"homepage": "http://www.loberon.de",
"role": "Contributor"
}
],
"support": {
"email": "support@shopmodule.com"
},
"homepage": "https://www.oxidmodule.com/",
"license": [
"GPL-3.0-only"
],
"extra": {
"oxideshop": {
"source-directory": "/src",
"target-directory": "d3/totp"
}
},
"require": {
"php": ">=5.6",
"ext-xmlwriter": "*",
"oxid-esales/oxideshop-ce": "6.2.1 - 6.7",
"spomky-labs/otphp": "^8.3",
"bacon/bacon-qr-code": "^1.0 || ^2.0",
"zendframework/zend-math": "^3.2"
},
"suggest": {
"d3/modcfg": "Provides automatic installation routines"
},
"autoload": {
"psr-4": {
"D3\\Totp\\": "../../../source/modules/d3/totp"
}
}
}

View File

@ -1,5 +1,9 @@
Die [2-Faktor-Authentisierung](https://de.wikipedia.org/wiki/Zwei-Faktor-Authentisierung) ermöglicht es den Shopbesuchern, neben der üblichen Kombination aus Benutzername und Passwort auch ein [zeitgesteuertes Einmalpasswort](https://de.wikipedia.org/wiki/Time-based_One-time_Password_Algorithmus) zur Anmeldung abfragen zu lassen. Dies erhöht die Sicherheit im Anmeldeprozess deutlich und macht auch Anmeldungen in öffentlichen Netzwerken oder Internet-Cafés sicherer.
Das abgefragte Einmalpasswort wird z.B. durch entsprechende Apps auf dem Smartphone erzeugt.
Das abgefragte Einmalpasswort wird z.B. durch entsprechende Apps auf dem Smartphone erzeugt. Die folgenden Apps sind Empfehlungen und können gegen andere nach dem TOTP-Standard arbeitende Apps getauscht werden.
[![Authenticator Apps bei Google Play](https://play.google.com/intl/en_us/badges/images/generic/de_badge_web_generic.png)](http://play.google.com/store/search?q=totp%20authenticator&c=apps)
[![Authenticator Apps im Apple Store](https://apps.apple.com/de/app/totp-authenticator-fast-2fa/id1404230533)](https://apps.apple.com/de/app/totp-authenticator-fast-2fa/id1404230533)
Die Einrichtung dieses 2. Faktors ist optional und lässt sich für jedes Benutzerkonto separat einrichten. Die Einrichtung erfolgt im "Mein Konto"-Bereich, über das Shopbackend kann die Einrichtung ebenfalls durchgeführt werden.

View File

@ -2,6 +2,11 @@
title: Changelog
---
## 1.1.0.0 (2022-09-30)
###
- optionale Verpflichtung zur 2FA-Nutzung fĂĽr Adminbenutzer
## 1.0.0.0 (2019-08-19)
### Added

View File

@ -1,9 +1,9 @@
{
"title": "<i class='fab fa-d3 d3fa-color-blue'></i> 2-Faktor-Authentisierung",
"moduleversion": "1.0.0.0",
"moduleversion": "1.1.0.0",
"titledesc": "fĂĽr den Oxid eShop",
"author": "DÂł Data Development",
"moduledate": "19.08.2019",
"moduledate": "30.09.2022",
"editors": "DS",
"tagline": "",
"image": "",

View File

@ -5,7 +5,7 @@ title: Schnellstart per Composer
## Schnellstart per Composer
```bash
php composer require {$composerident} –-update-no-dev
php composer require {$composerident} --update-no-dev
```
Detailliertere Angaben zur Installation entnehmen Sie bitte den folgenden Seiten.

View File

@ -1,27 +1,27 @@
CREATE TABLE IF NOT EXISTS `d3totp` (
`OXID` CHAR(32) NOT NULL ,
`OXUSERID` CHAR(32) NOT NULL ,
`USETOTP` TINYINT(1) NOT NULL DEFAULT 0,
`SEED` VARCHAR(256) NOT NULL ,
`OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
PRIMARY KEY (`OXID`) ,
UNIQUE KEY `OXUSERID` (`OXUSERID`)
)
ENGINE=InnoDB
COMMENT='totp setting';
CREATE TABLE IF NOT EXISTS `d3totp_backupcodes` (
`OXID` CHAR(32) NOT NULL ,
`OXUSERID` CHAR(32) NOT NULL COMMENT 'user id',
`BACKUPCODE` VARCHAR(64) NOT NULL COMMENT 'BackupCode',
`OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
PRIMARY KEY (`OXID`) ,
KEY `OXUSERID` (`OXUSERID`) ,
KEY `BACKUPCODE` (`BACKUPCODE`)
)
ENGINE=InnoDB
COMMENT='totp backup codes';
INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
('39f744f17e974988e515558698a29df4', '76282e134ad4e40a3578e121a6cb1f6a', 1, 1, 'index.php?cl=d3_account_totp', 'en/2-factor-authintication/', 'static', 0, 0, '', NOW()),
('39f744f17e974988e515558698a29df4', 'c1f8b5506e2b5d6ac184dcc5ebdfb591', 1, 0, 'index.php?cl=d3_account_totp', '2-faktor-authentisierung/', 'static', 0, 0, '', NOW());
CREATE TABLE IF NOT EXISTS `d3totp` (
`OXID` CHAR(32) NOT NULL ,
`OXUSERID` CHAR(32) NOT NULL ,
`USETOTP` TINYINT(1) NOT NULL DEFAULT 0,
`SEED` VARCHAR(256) NOT NULL ,
`OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
PRIMARY KEY (`OXID`) ,
UNIQUE KEY `OXUSERID` (`OXUSERID`)
)
ENGINE=InnoDB
COMMENT='totp setting';
CREATE TABLE IF NOT EXISTS `d3totp_backupcodes` (
`OXID` CHAR(32) NOT NULL ,
`OXUSERID` CHAR(32) NOT NULL COMMENT 'user id',
`BACKUPCODE` VARCHAR(64) NOT NULL COMMENT 'BackupCode',
`OXTIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
PRIMARY KEY (`OXID`) ,
KEY `OXUSERID` (`OXUSERID`) ,
KEY `BACKUPCODE` (`BACKUPCODE`)
)
ENGINE=InnoDB
COMMENT='totp backup codes';
INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
('39f744f17e974988e515558698a29df4', '76282e134ad4e40a3578e121a6cb1f6a', 1, 1, 'index.php?cl=d3_account_totp', 'en/2-factor-authintication/', 'static', 0, 0, '', NOW()),
('39f744f17e974988e515558698a29df4', 'c1f8b5506e2b5d6ac184dcc5ebdfb591', 1, 0, 'index.php?cl=d3_account_totp', '2-faktor-authentisierung/', 'static', 0, 0, '', NOW());

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace D3\Totp\Application\Controller\Admin;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session;
class d3force_2fa extends d3user_totp
{
public function render()
{
$this->addTplParam('force2FA', true);
$userID = $this->d3GetSessionObject()->getVariable("auth");
$this->_sEditObjectId = $userID;
return parent::render();
}
protected function _authorize()
{
$userID = $this->d3GetSessionObject()->getVariable("auth");
return ($this->d3IsAdminForce2FA() && !empty($userID));
}
/**
* @return Session
*/
private function d3GetSessionObject()
{
return Registry::getSession();
}
/**
* @return bool
*/
private function d3IsAdminForce2FA()
{
return $this->isAdmin() &&
Registry::getConfig()->getConfigParam('D3_TOTP_ADMIN_FORCE_2FA') == true;
}
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace D3\Totp\Application\Factory;
use BaconQrCode\Renderer\RendererInterface;
use BaconQrCode\Renderer\Image\Svg; // v1.0.3
use BaconQrCode\Renderer\ImageRenderer; // v2.0.0
use BaconQrCode\Renderer\Image\SvgImageBackEnd; // v2.0.0
use BaconQrCode\Renderer\RendererStyle\RendererStyle; // v2.0.0
class BaconQrCodeFactory
{
/**
* @return RendererInterface
*/
public static function renderer($size)
{
if (class_exists(Svg::class)) {
return self::v100($size);
}
return self::v200($size);
}
private static function v200($size)
{
$renderer = oxNew(
ImageRenderer::class,
oxNew(RendererStyle::class, $size),
oxNew(SvgImageBackEnd::class),
);
return $renderer;
}
private static function v100($size)
{
$renderer = oxNew(Svg::class);
$renderer->setHeight($size);
$renderer->setWidth($size);
return $renderer;
}
}

View File

@ -15,9 +15,9 @@
namespace D3\Totp\Application\Model;
use BaconQrCode\Renderer\Image\Svg;
use BaconQrCode\Renderer\RendererInterface;
use BaconQrCode\Writer;
use D3\Totp\Application\Factory\BaconQrCodeFactory;
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
use Doctrine\DBAL\DBALException;
use OTPHP\TOTP;
@ -177,10 +177,7 @@ class d3totp extends BaseModel
*/
public function getQrCodeElement()
{
$renderer = oxNew(Svg::class);
$renderer->setHeight(200);
$renderer->setWidth(200);
$renderer = BaconQrCodeFactory::renderer(200);
$writer = $this->d3GetWriter($renderer);
return $writer->writeString($this->getTotp()->getProvisioningUri());
}

View File

@ -34,6 +34,11 @@ $aLang = [
'D3_TOTP_CURROTP' => 'Bestätigung mit Einmalpasswort',
'D3_TOTP_CURROTP_HELP' => 'Haben Sie dieses Kundenkonto in Ihrer Authentisierungs-App registriert, generieren Sie damit ein Einmalpasswort, tragen Sie es hier ein und senden das Formular direkt darauf hin ab.',
'D3_TOTP_FORCE2FATITLE' => 'Verpflichtet Zwei-Faktor-Authentisierung',
'D3_TOTP_FORCE2FASUB' => 'Alle Administratoren mĂĽssen es aktivieren',
'D3_TOTP_ADMINBACKEND' => 'Admin-Oberfläche',
'D3_TOTP_ADMINCONTINUE' => 'weiter',
'D3_TOTP_REGISTEREXIST' => 'vorhandene Registrierung',
'D3_TOTP_REGISTERDELETE' => 'Registrierung löschen',
'D3_TOTP_REGISTERDELETE_DESC' => 'Um die Registrierung zu ändern, löschen Sie diese bitte vorerst. Sie können sofort im Anschluss eine neue Registrierung anlegen.<br>Wenn Sie die Registrierung löschen, ist das Konto nicht mehr durch die Zwei-Faktor-Authentisierung geschützt.',
@ -48,4 +53,6 @@ $aLang = [
'D3_TOTP_ERROR_UNVALID' => 'Das Einmalpasswort ist ungĂĽltig.',
'D3_TOTP_ALREADY_EXIST' => 'Die Registrierung wurde schon gespeichert.',
'SHOP_MODULE_D3_TOTP_ADMIN_FORCE_2FA' => 'Administratoren sind verpflichtet 2FA zu aktivieren'
];

View File

@ -34,6 +34,11 @@ $aLang = [
'D3_TOTP_CURROTP' => 'Confirmation with one-time password',
'D3_TOTP_CURROTP_HELP' => 'If you have registered this customer account in your authentication app, you generate a one-time password, enter it here and send the form out immediately.',
'D3_TOTP_FORCE2FATITLE' => 'Mandates two-factor authentication',
'D3_TOTP_FORCE2FASUB' => 'All administrators need to activate it',
'D3_TOTP_ADMINBACKEND' => 'Admin-Backend',
'D3_TOTP_ADMINCONTINUE' => 'continue',
'D3_TOTP_REGISTEREXIST' => 'existing registration',
'D3_TOTP_REGISTERDELETE' => 'Delete registration',
'D3_TOTP_REGISTERDELETE_DESC' => 'To change the registration, please delete it. You can then immediately create a new registration. <br> If you delete the registration, the account is no longer protected by the two-factor authentication.',
@ -48,4 +53,6 @@ $aLang = [
'D3_TOTP_ERROR_UNVALID' => 'The one-time password is invalid.',
'D3_TOTP_ALREADY_EXIST' => 'The registration has already been saved.',
'SHOP_MODULE_D3_TOTP_ADMIN_FORCE_2FA' => 'Administrators are required to activate 2FA'
];

View File

@ -14,8 +14,25 @@
td.edittext {
white-space: normal;
}
.hero {
display: inline-block;
}
.hero > h1 {
padding: 0.3em 0;
}
.hero > div {
text-align: right;
color: #6c7c98;
}
</style>
[{if $force2FA}]
<div class="hero">
<h1>[{oxmultilang ident="D3_TOTP_FORCE2FATITLE"}]</h1>
<div>[{oxmultilang ident="D3_TOTP_FORCE2FASUB"}]</div>
</div>
[{/if}]
<form name="transfer" id="transfer" action="[{$oViewConf->getSelfLink()}]" method="post">
[{$oViewConf->getHiddenSid()}]
<input type="hidden" name="oxid" value="[{$oxid}]">
@ -60,6 +77,22 @@
[{oxinputhelp ident="D3_TOTP_QRCODE_HELP"}]
</td>
</tr>
[{elseif $force2FA}]
<tr>
<td class="edittext" colspan="2">
<h4>[{oxmultilang ident="D3_TOTP_ADMINBACKEND"}]</h4>
</td>
</tr>
<tr>
<td class="edittext" colspan="2">
<input
type="submit" class="edittext" id="oLockButton" name="delete"
value="[{oxmultilang ident="D3_TOTP_ADMINCONTINUE"}]"
onClick="document.myedit.fnc.value='';document.myedit.cl.value='admin_start'"
>
</td>
</tr>
[{else}]
<tr>
<td class="edittext" colspan="2">
@ -153,5 +186,7 @@
[{/if}]
</form>
[{include file="bottomnaviitem.tpl"}]
[{include file="bottomitem.tpl"}]
[{if !$force2FA}]
[{include file="bottomnaviitem.tpl"}]
[{include file="bottomitem.tpl"}]
[{/if}]

View File

@ -1,60 +1,60 @@
<?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\Totp\Modules\Application\Component
{
use OxidEsales\Eshop\Application\Component\UserComponent;
class d3_totp_UserComponent_parent extends UserComponent { }
}
namespace D3\Totp\Modules\Application\Controller
{
use OxidEsales\Eshop\Application\Controller\OrderController;
use OxidEsales\Eshop\Application\Controller\PaymentController;
use OxidEsales\Eshop\Application\Controller\UserController;
class d3_totp_UserController_parent extends UserController { }
class d3_totp_PaymentController_parent extends PaymentController { }
class d3_totp_OrderController_parent extends OrderController { }
}
namespace D3\Totp\Modules\Application\Controller\Admin
{
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
class d3_totp_LoginController_parent extends LoginController { }
}
namespace D3\Totp\Modules\Application\Model
{
use OxidEsales\Eshop\Application\Model\User;
class d3_totp_user_parent extends User { }
}
namespace D3\Totp\Modules\Core
{
use OxidEsales\Eshop\Core\Utils;
class d3_totp_utils_parent extends Utils { }
<?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\Totp\Modules\Application\Component
{
use OxidEsales\Eshop\Application\Component\UserComponent;
class d3_totp_UserComponent_parent extends UserComponent { }
}
namespace D3\Totp\Modules\Application\Controller
{
use OxidEsales\Eshop\Application\Controller\OrderController;
use OxidEsales\Eshop\Application\Controller\PaymentController;
use OxidEsales\Eshop\Application\Controller\UserController;
class d3_totp_UserController_parent extends UserController { }
class d3_totp_PaymentController_parent extends PaymentController { }
class d3_totp_OrderController_parent extends OrderController { }
}
namespace D3\Totp\Modules\Application\Controller\Admin
{
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
class d3_totp_LoginController_parent extends LoginController { }
}
namespace D3\Totp\Modules\Application\Model
{
use OxidEsales\Eshop\Application\Model\User;
class d3_totp_user_parent extends User { }
}
namespace D3\Totp\Modules\Core
{
use OxidEsales\Eshop\Core\Utils;
class d3_totp_utils_parent extends Utils { }
}

View File

@ -1,68 +1,93 @@
<?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\Totp\Modules\Core;
use D3\Totp\Application\Model\d3totp;
use Doctrine\DBAL\DBALException;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session;
class d3_totp_utils extends d3_totp_utils_parent
{
/**
* @return bool
* @throws DBALException
* @throws DatabaseConnectionException
*/
public function checkAccessRights()
{
$blAuth = parent::checkAccessRights();
$userID = $this->d3GetSessionObject()->getVariable("auth");
$totpAuth = (bool) $this->d3GetSessionObject()->getVariable(d3totp::TOTP_SESSION_VARNAME);
/** @var d3totp $totp */
$totp = $this->d3GetTotpObject();
$totp->loadByUserId($userID);
if ($blAuth && $totp->isActive() && false === $totpAuth) {
$this->redirect('index.php?cl=login', true, 302);
if (false == defined('OXID_PHP_UNIT')) {
// @codeCoverageIgnoreStart
exit;
// @codeCoverageIgnoreEnd
}
}
return $blAuth;
}
/**
* @return Session
*/
public function d3GetSessionObject()
{
return Registry::getSession();
}
/**
* @return d3totp
*/
public function d3GetTotpObject()
{
return oxNew(d3totp::class);
}
}
<?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\Totp\Modules\Core;
use D3\Totp\Application\Model\d3totp;
use Doctrine\DBAL\DBALException;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session;
class d3_totp_utils extends d3_totp_utils_parent
{
/**
* @return bool
* @throws DBALException
* @throws DatabaseConnectionException
*/
public function checkAccessRights()
{
$blAuth = parent::checkAccessRights();
$userID = $this->d3GetSessionObject()->getVariable("auth");
$totpAuth = (bool) $this->d3GetSessionObject()->getVariable(d3totp::TOTP_SESSION_VARNAME);
/** @var d3totp $totp */
$totp = $this->d3GetTotpObject();
$totp->loadByUserId($userID);
//checkt ob alle Admin 2FA aktiviert hat
//todo braucht Unit Test
if (
$this->d3IsAdminForce2FA()
&& $blAuth
&& $totp->isActive() === false
) {
$this->redirect('index.php?cl=d3force_2fa', true, 302);
if (false == defined('OXID_PHP_UNIT')) {
// @codeCoverageIgnoreStart
exit;
// @codeCoverageIgnoreEnd
}
}
//staten der prĂĽfung vom einmalpasswort
if ($blAuth && $totp->isActive() && false === $totpAuth) {
$this->redirect('index.php?cl=login', true, 302);
if (false == defined('OXID_PHP_UNIT')) {
// @codeCoverageIgnoreStart
exit;
// @codeCoverageIgnoreEnd
}
}
return $blAuth;
}
/**
* @return Session
*/
public function d3GetSessionObject()
{
return Registry::getSession();
}
/**
* @return d3totp
*/
public function d3GetTotpObject()
{
return oxNew(d3totp::class);
}
/**
* @return bool
*/
private function d3IsAdminForce2FA()
{
return $this->isAdmin() &&
Registry::getConfig()->getConfigParam('D3_TOTP_ADMIN_FORCE_2FA') == true;
}
}

View File

@ -16,6 +16,7 @@
*/
use D3\Totp\Application\Controller\Admin\d3user_totp;
use D3\Totp\Application\Controller\Admin\d3force_2fa;
use D3\Totp\Application\Controller\d3_account_totp;
use D3\Totp\Application\Controller\d3totplogin;
use D3\Totp\Modules\Application\Component\d3_totp_UserComponent;
@ -40,8 +41,6 @@ use OxidEsales\Eshop\Application\Model as OxidModel;
*/
$sMetadataVersion = '2.0';
$logo = (class_exists(d3utils::class) ? d3utils::getInstance()->getD3Logo() : 'D&sup3;');
$sModuleId = 'd3totp';
/**
* Module information
@ -49,15 +48,19 @@ $sModuleId = 'd3totp';
$aModule = [
'id' => $sModuleId,
'title' => [
'de' => $logo.' Zwei-Faktor-Authentisierung',
'en' => $logo.' two-factor authentication',
'de' =>
'<svg style="height:1em;width:1em"><image xlink:href="https://logos.oxidmodule.com/d3logo.svg" style="height:1em;width:1em" /></svg> '.
'Zwei-Faktor-Authentisierung',
'en' =>
'<svg style="height:1em;width:1em"><image xlink:href="https://logos.oxidmodule.com/d3logo.svg" style="height:1em;width:1em" /></svg> '.
'two-factor authentication',
],
'description' => [
'de' => 'Zwei-Faktor-Authentisierung (TOTP) f&uuml;r OXID eSales Shop',
'en' => 'Two-factor authentication (TOTP) for OXID eSales shop',
],
'thumbnail' => 'picture.png',
'version' => '1.0.0.0',
'version' => '1.1.0.0',
'author' => 'D&sup3; Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'http://www.oxidmodule.com/',
@ -72,6 +75,7 @@ $aModule = [
],
'controllers' => [
'd3user_totp' => d3user_totp::class,
'd3force_2fa' => d3force_2fa::class,
'd3totplogin' => d3totplogin::class,
'd3_account_totp' => d3_account_totp::class,
],
@ -80,6 +84,14 @@ $aModule = [
'd3totplogin.tpl' => 'd3/totp/Application/views/tpl/d3totplogin.tpl',
'd3_account_totp.tpl' => 'd3/totp/Application/views/tpl/d3_account_totp.tpl',
],
'settings' => [
[
'group' => 'main',
'name' => 'D3_TOTP_ADMIN_FORCE_2FA',
'type' => 'bool',
'value' => false,
]
],
'events' => [
'onActivate' => '\D3\Totp\Setup\Events::onActivate',
'onDeactivate' => '\D3\Totp\Setup\Events::onDeactivate',
@ -94,6 +106,6 @@ $aModule = [
'template' => 'page/account/inc/account_menu.tpl',
'block' => 'account_menu',
'file' => 'Application/views/blocks/page/account/inc/account_menu.tpl',
]
],
]
];

View File

@ -17,8 +17,8 @@
namespace D3\Totp\tests\unit\Application\Model;
use BaconQrCode\Renderer\Image\Svg;
use BaconQrCode\Writer;
use D3\Totp\Application\Factory\BaconQrCodeFactory;
use D3\Totp\Application\Model\d3backupcodelist;
use D3\Totp\Application\Model\d3totp;
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
@ -484,7 +484,7 @@ class d3totpTest extends d3TotpUnitTestCase
'getFieldData',
));
$oUserMock->method('getFieldData')->willReturn('username');
/** @var d3totp|PHPUnit_Framework_MockObject_MockObject $oModelMock */
$oModelMock = $this->getMock(d3totp::class, array(
'getUser',
@ -544,7 +544,7 @@ class d3totpTest extends d3TotpUnitTestCase
'getQrCodeUri'
));
$oTotpMock->expects($this->once())->method('getQrCodeUri')->willReturn(true);
/** @var d3totp|PHPUnit_Framework_MockObject_MockObject $oModelMock */
$oModelMock = $this->getMock(d3totp::class, array(
'getTotp'
@ -562,7 +562,7 @@ class d3totpTest extends d3TotpUnitTestCase
*/
public function getQrCodeElement()
{
$renderer = oxNew(Svg::class);
$renderer = BaconQrCodeFactory::renderer(200);
/** @var d3totp|PHPUnit_Framework_MockObject_MockObject $oTotpMock */
$oTotpMock = $this->getMock(d3totp::class, array(
@ -595,14 +595,14 @@ class d3totpTest extends d3TotpUnitTestCase
*/
public function d3GetWriterReturnsRightInstance()
{
$renderer = oxNew(Svg::class);
$renderer = BaconQrCodeFactory::renderer(200);;
$this->assertInstanceOf(
Writer::class,
$this->callMethod($this->_oModel, 'd3GetWriter', [$renderer])
);
}
/**
* @test
* @throws ReflectionException
@ -878,4 +878,4 @@ class d3totpTest extends d3TotpUnitTestCase
$this->callMethod($this->_oModel, 'delete')
);
}
}
}