From 2d1f99a8ce20c8be30702cce558c8f6a95fe28a8 Mon Sep 17 00:00:00 2001 From: djmaze Date: Fri, 23 Jul 2021 13:36:38 +0200 Subject: [PATCH] Get 2FA plugin somesort of working --- plugins/two-factor-auth/index.php | 114 ++++------- .../two-factor-auth/js/TwoFactorAuthLogin.js | 23 +++ .../js/TwoFactorAuthSettings.js | 25 +-- plugins/two-factor-auth/langs/de_DE.ini | 3 - plugins/two-factor-auth/langs/en.ini | 3 - plugins/two-factor-auth/langs/es_ES.ini | 3 - plugins/two-factor-auth/langs/fr_FR.ini | 3 - plugins/two-factor-auth/langs/hu-HU.ini | 3 - plugins/two-factor-auth/langs/nl_NL.ini | 3 - plugins/two-factor-auth/langs/sv-SE.ini | 3 - plugins/two-factor-auth/langs/zh_CN.ini | 3 - .../templates/TwoFactorAuthSettings.html | 181 ++++++++---------- 12 files changed, 151 insertions(+), 216 deletions(-) create mode 100644 plugins/two-factor-auth/js/TwoFactorAuthLogin.js diff --git a/plugins/two-factor-auth/index.php b/plugins/two-factor-auth/index.php index 87f4f9da3..1a4b394e3 100644 --- a/plugins/two-factor-auth/index.php +++ b/plugins/two-factor-auth/index.php @@ -1,8 +1,4 @@ DefaultResponse(__FUNCTION__, -$this->FalseResponse(__FUNCTION__); -*/ use \RainLoop\Exceptions\ClientException; @@ -14,21 +10,18 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin RELEASE = '2021-07-22', REQUIRED = '2.5.4', CATEGORY = 'Login', - DESCRIPTION = 'This plugin allows you to to have TOTP'; + DESCRIPTION = 'This plugin allows you to have TOTP 2FA'; - // \RainLoop\Notifications\ const AccountTwoFactorAuthRequired = 120, - AccountTwoFactorAuthError = 121, - - Capa_TWO_FACTOR = 'TWO_FACTOR', - Capa_TWO_FACTOR_FORCE = 'TWO_FACTOR_FORCE'; + AccountTwoFactorAuthError = 121; public function Init() : void { $this->UseLangs(true); // $this->addCss('style.less'); + $this->addJs('js/TwoFactorAuthLogin.js'); $this->addJs('js/TwoFactorAuthSettings.js'); $this->addHook('login.success', 'DoLogin'); @@ -44,73 +37,39 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $this->addTemplate('templates/PopupsTwoFactorAuthTest.html'); } - public function configMapping() : array - { - return [ - \RainLoop\Plugins\Property::NewInstance('allow_two_factor_auth') - ->SetLabel('TAB_SECURITY/LABEL_ALLOW_TWO_STEP') - ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL), - \RainLoop\Plugins\Property::NewInstance('force_two_factor_auth') - ->SetLabel('TAB_SECURITY/LABEL_FORCE_TWO_STEP') - ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) - ]; - } - public function DoLogin(\RainLoop\Model\Account $oAccount) { - // Stripped from \RainLoop\Actions::LoginProcess if ($this->TwoFactorAuthProvider($oAccount)) { $aData = $this->getTwoFactorInfo($oAccount); if ($aData && isset($aData['IsSet'], $aData['Enable']) && !empty($aData['Secret']) && $aData['IsSet'] && $aData['Enable']) { - $sSecretHash = \md5(APP_SALT . $aData['Secret'] . Utils::Fingerprint()); - $sSecretCookieHash = Utils::GetCookie(self::AUTH_TFA_SIGN_ME_TOKEN_KEY, ''); + $sCode = \trim($this->jsonParam('totp_code', '')); + if (empty($sCode)) { + $this->Logger()->Write('TFA: Required Code for ' . $oAccount->ParentEmailHelper() . ' account.'); - if (empty($sSecretCookieHash) || $sSecretHash !== $sSecretCookieHash) { - $sAdditionalCode = \trim($this->jsonParam('AdditionalCode', '')); - if (empty($sAdditionalCode)) { - $this->Logger()->Write('TFA: Required Code for ' . $oAccount->ParentEmailHelper() . ' account.'); + throw new ClientException(static::AccountTwoFactorAuthRequired); + } else { + $this->Logger()->Write('TFA: Verify Code for ' . $oAccount->ParentEmailHelper() . ' account.'); - throw new Exceptions\ClientException(Notifications::AccountTwoFactorAuthRequired); - } else { - $this->Logger()->Write('TFA: Verify Code for ' . $oAccount->ParentEmailHelper() . ' account.'); + $bUseBackupCode = false; + if (6 < \strlen($sCode) && !empty($aData['BackupCodes'])) { + $aBackupCodes = \explode(' ', \trim(\preg_replace('/[^\d]+/', ' ', $aData['BackupCodes']))); + $bUseBackupCode = \in_array($sCode, $aBackupCodes); - $bUseBackupCode = false; - if (6 < \strlen($sAdditionalCode) && !empty($aData['BackupCodes'])) { - $aBackupCodes = \explode(' ', \trim(\preg_replace('/[^\d]+/', ' ', $aData['BackupCodes']))); - $bUseBackupCode = \in_array($sAdditionalCode, $aBackupCodes); - - if ($bUseBackupCode) { - $this->removeBackupCodeFromTwoFactorInfo($oAccount->ParentEmailHelper(), $sAdditionalCode); - } + if ($bUseBackupCode) { + $this->removeBackupCodeFromTwoFactorInfo($oAccount->ParentEmailHelper(), $sCode); } + } - if (!$bUseBackupCode && !$this->TwoFactorAuthProvider($oAccount)->VerifyCode($aData['Secret'], $sAdditionalCode)) { - $this->Manager()->Actions()->loginErrorDelay(); + if (!$bUseBackupCode && !$this->TwoFactorAuthProvider($oAccount)->VerifyCode($aData['Secret'], $sCode)) { + $this->Manager()->Actions()->loginErrorDelay(); - $this->Manager()->Actions()->LoggerAuthHelper($oAccount); + $this->Manager()->Actions()->LoggerAuthHelper($oAccount); - throw new Exceptions\ClientException(Notifications::AccountTwoFactorAuthError); - } - - // $bAdditionalCodeSignMe -// if ('1' === (string) $this->Manager()->Actions()->GetActionParam('AdditionalCodeSignMe', '0')) { - if ('1' === (string) $this->jsonParam('AdditionalCodeSignMe', '0')) { - Utils::SetCookie(self::AUTH_TFA_SIGN_ME_TOKEN_KEY, $sSecretHash, - \time() + 60 * 60 * 24 * 14); - } + throw new ClientException(static::AccountTwoFactorAuthError); } } } } -/* - // Stripped from \RainLoop\Actions\User::DoLogin - if (Notifications::AccountTwoFactorAuthRequired === $oException->getCode()) - { - return $this->DefaultResponse(__FUNCTION__, true, array( - 'TwoFactorAuth' => true - )); - } -*/ } public function DoGetTwoFactorInfo() : array @@ -118,10 +77,10 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } - return $this->DefaultResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount, true)); + return $this->jsonResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount, true)); } public function DoCreateTwoFactorSecret() : array @@ -129,7 +88,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } $sEmail = $oAccount->ParentEmailHelper(); @@ -153,9 +112,9 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin )) ); - $this->Manager()->Actions()->requestSleep(); +// $this->Manager()->Actions()->requestSleep(); - return $this->DefaultResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount)); + return $this->jsonResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount)); } public function DoShowTwoFactorSecret() : array @@ -163,13 +122,13 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } $aResult = $this->getTwoFactorInfo($oAccount); unset($aResult['BackupCodes']); - return $this->DefaultResponse(__FUNCTION__, $aResult); + return $this->jsonResponse(__FUNCTION__, $aResult); } public function DoEnableTwoFactor() : array @@ -177,7 +136,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } // $this->Manager()->Actions()->setSettingsFromParams($oSettings, 'EnableTwoFactor', 'bool'); @@ -205,7 +164,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin ); } - return $this->DefaultResponse(__FUNCTION__, $bResult); + return $this->jsonResponse(__FUNCTION__, $bResult); } public function DoVerifyTwoFactorCode() : array @@ -213,7 +172,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } $sCode = \trim($this->jsonParam('Code', '')); @@ -226,9 +185,9 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin // $this->TwoFactorAuthProvider($oAccount)->VerifyCode($sSecret, $sCode) // )); - $this->Manager()->Actions()->requestSleep(); +// $this->Manager()->Actions()->requestSleep(); - return $this->DefaultResponse(__FUNCTION__, + return $this->jsonResponse(__FUNCTION__, $this->TwoFactorAuthProvider($oAccount)->VerifyCode($sSecret, $sCode)); } @@ -237,7 +196,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin $oAccount = $this->getAccountFromToken(); if (!$this->TwoFactorAuthProvider($oAccount)) { - return $this->FalseResponse(__FUNCTION__); + return $this->jsonResponse(__FUNCTION__, false); } $this->StorageProvider()->Clear($oAccount, @@ -245,7 +204,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin 'two_factor' ); - return $this->DefaultResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount, true)); + return $this->jsonResponse(__FUNCTION__, $this->getTwoFactorInfo($oAccount, true)); } protected function Logger() : \RainLoop\Providers\TwoFactorAuth @@ -264,10 +223,7 @@ class TwoFactorAuthPlugin extends \RainLoop\Plugins\AbstractPlugin private $oTwoFactorAuthProvider; protected function TwoFactorAuthProvider(\RainLoop\Model\Account $oAccount) : ?TwoFactorAuthInterface { -// if ($this->Config()->Get('plugin', 'allow_two_factor_auth', 0)) -// if ($this->Config()->Get('plugin', 'force_two_factor_auth', 0)) - - if (!$this->oTwoFactorAuthProvider && $this->Manager()->Actions()->GetCapa(false, static::Capa_TWO_FACTOR, $oAccount)) { + if (!$this->oTwoFactorAuthProvider) { require __DIR__ . '/providers/interface.php'; require __DIR__ . '/providers/totp.php'; $this->oTwoFactorAuthProvider = new TwoFactorAuthTotp(); diff --git a/plugins/two-factor-auth/js/TwoFactorAuthLogin.js b/plugins/two-factor-auth/js/TwoFactorAuthLogin.js new file mode 100644 index 000000000..af8e48950 --- /dev/null +++ b/plugins/two-factor-auth/js/TwoFactorAuthLogin.js @@ -0,0 +1,23 @@ + +(rl => { + + rl && addEventListener('rl-view-model', e => { + if (e.detail && 'Login' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('#plugin-Login-BottomControlGroup'), + placeholder = 'LOGIN/LABEL_VERIFICATION_CODE'; + if (container) { + container.append(Element.fromHTML('
' + + '
' + + '' + + '🔑' + + '
' + + '
')); + } + } + }); + +})(window.rl); diff --git a/plugins/two-factor-auth/js/TwoFactorAuthSettings.js b/plugins/two-factor-auth/js/TwoFactorAuthSettings.js index c4e106d92..e25242d27 100644 --- a/plugins/two-factor-auth/js/TwoFactorAuthSettings.js +++ b/plugins/two-factor-auth/js/TwoFactorAuthSettings.js @@ -5,11 +5,6 @@ import { trigger as translatorTrigger } from 'Common/Translator'; (rl => { if (rl) { const - Capa = { - TwoFactor: 'TWO_FACTOR', - TwoFactorForce: 'TWO_FACTOR_FORCE', - }, - pString = value => null != value ? '' + value : '', Remote = new class { @@ -56,10 +51,8 @@ class TwoFactorAuthSettings this.viewEnable_ = ko.observable(false); - this.capaTwoFactor = rl.settings.capa(Capa.TwoFactor); - const fn = iError => iError && this.viewEnable_(false); - this.addComputables({ + Object.entries({ viewEnable: { read: this.viewEnable_, write: (value) => { @@ -92,12 +85,16 @@ class TwoFactorAuthSettings }, twoFactorAllowedEnable: () => this.viewEnable() || this.twoFactorTested() - }); + }).forEach(([key, fn]) => this[key] = ko.computed(fn)); this.onResult = this.onResult.bind(this); this.onShowSecretResult = this.onShowSecretResult.bind(this); } + configureTwoFactor() { +// showScreenPopup(require('View/Popup/TwoFactorConfiguration')); + } + showSecret() { this.secreting(true); rl.pluginRemoteRequest(this.onShowSecretResult, 'ShowTwoFactorSecret'); @@ -180,7 +177,7 @@ class TwoFactorAuthSettings this.viewBackupCodes(pString(oData.Result.BackupCodes).replace(/[\s]+/g, ' ')); this.viewUrlTitle(pString(oData.Result.UrlTitle)); - this.viewUrl(qr.toDataURL({ level: 'M', size: 8, value: this.getQr() })); + this.viewUrl(null/*qr.toDataURL({ level: 'M', size: 8, value: this.getQr() })*/); } } @@ -194,15 +191,13 @@ class TwoFactorAuthSettings } else { this.viewSecret(pString(data.Result.Secret)); this.viewUrlTitle(pString(data.Result.UrlTitle)); - this.viewUrl(qr.toDataURL({ level: 'M', size: 6, value: this.getQr() })); + this.viewUrl(null/*qr.toDataURL({ level: 'M', size: 6, value: this.getQr() })*/); } } onBuild() { - if (this.capaTwoFactor) { - this.processing(true); - rl.pluginRemoteRequest(this.onResult, 'GetTwoFactorInfo'); - } + this.processing(true); + rl.pluginRemoteRequest(this.onResult, 'GetTwoFactorInfo'); } } diff --git a/plugins/two-factor-auth/langs/de_DE.ini b/plugins/two-factor-auth/langs/de_DE.ini index 367e8a324..3658ae26a 100644 --- a/plugins/two-factor-auth/langs/de_DE.ini +++ b/plugins/two-factor-auth/langs/de_DE.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "Zwei-Faktor-Authentifizierung erlauben" -LABEL_FORCE_TWO_STEP = "Zwei-Faktor-Authentifizierung erzwingen" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "Zwei-Faktor-Authentifizierung" LABEL_ENABLE_TWO_FACTOR = "Zwei-Faktor-Authentifizierung aktivieren" diff --git a/plugins/two-factor-auth/langs/en.ini b/plugins/two-factor-auth/langs/en.ini index ab46a74f4..211f2fb25 100644 --- a/plugins/two-factor-auth/langs/en.ini +++ b/plugins/two-factor-auth/langs/en.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "Allow 2-Step Verification" -LABEL_FORCE_TWO_STEP = "Enforce 2-Step Verification" [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "2-Step verification test" LABEL_CODE = "Code" diff --git a/plugins/two-factor-auth/langs/es_ES.ini b/plugins/two-factor-auth/langs/es_ES.ini index 5e8e4ebac..56f4c8894 100644 --- a/plugins/two-factor-auth/langs/es_ES.ini +++ b/plugins/two-factor-auth/langs/es_ES.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "Activar la verificación de 2 pasos" -LABEL_FORCE_TWO_STEP = "Forzar la Autenticación en 2 pasos" [POPUPS_TWO_FACTOR_TEST] TITLE_TEST_CODE = "Prueba de verificación de 2 pasos" LABEL_CODE = "Código" diff --git a/plugins/two-factor-auth/langs/fr_FR.ini b/plugins/two-factor-auth/langs/fr_FR.ini index 0e1f580a7..31bad129b 100644 --- a/plugins/two-factor-auth/langs/fr_FR.ini +++ b/plugins/two-factor-auth/langs/fr_FR.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "Autoriser l'authentification en deux étapes" -LABEL_FORCE_TWO_STEP = "Forcer l'authentification en deux étapes" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "Authentification en deux étapes" LABEL_ENABLE_TWO_FACTOR = "Activer l'authentification en deux étapes" diff --git a/plugins/two-factor-auth/langs/hu-HU.ini b/plugins/two-factor-auth/langs/hu-HU.ini index e60ed1daf..efe29a77c 100644 --- a/plugins/two-factor-auth/langs/hu-HU.ini +++ b/plugins/two-factor-auth/langs/hu-HU.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "2 lépcsős hitelesítés engedélyezése" -LABEL_FORCE_TWO_STEP = "2 lépcsős hitelesítés kényszerítése" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "2 lépcsős hitelesítés" LABEL_ENABLE_TWO_FACTOR = "2 lépcsős hitelesítés engedélyezése" diff --git a/plugins/two-factor-auth/langs/nl_NL.ini b/plugins/two-factor-auth/langs/nl_NL.ini index 52c2fcce9..bd720f11e 100644 --- a/plugins/two-factor-auth/langs/nl_NL.ini +++ b/plugins/two-factor-auth/langs/nl_NL.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "2-Stap verificatie toestaan" -LABEL_FORCE_TWO_STEP = "2-Stap verificatie afdwingen" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "2-Stap verificatie" LABEL_ENABLE_TWO_FACTOR = "Gebruik 2-Stap verificatie" diff --git a/plugins/two-factor-auth/langs/sv-SE.ini b/plugins/two-factor-auth/langs/sv-SE.ini index 101aed016..9097b3af1 100644 --- a/plugins/two-factor-auth/langs/sv-SE.ini +++ b/plugins/two-factor-auth/langs/sv-SE.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "Låt 2-tvåstegsverifiering" -LABEL_FORCE_TWO_STEP = "Driva 2-tvåstegsverifiering" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "Tvåstegsverifiering (TOTP)" LABEL_ENABLE_TWO_FACTOR = "Aktivera tvåstegsverifiering" diff --git a/plugins/two-factor-auth/langs/zh_CN.ini b/plugins/two-factor-auth/langs/zh_CN.ini index 5395a41d8..0421e208a 100644 --- a/plugins/two-factor-auth/langs/zh_CN.ini +++ b/plugins/two-factor-auth/langs/zh_CN.ini @@ -1,6 +1,3 @@ -[TAB_SECURITY] -LABEL_ALLOW_TWO_STEP = "允许两步验证" -LABEL_FORCE_TWO_STEP = "强制使用两步验证" [POPUPS_TWO_FACTOR_CFG] LEGEND_TWO_FACTOR_AUTH = "两步验证 (TOTP)" LABEL_ENABLE_TWO_FACTOR = "启用两步验证" diff --git a/plugins/two-factor-auth/templates/TwoFactorAuthSettings.html b/plugins/two-factor-auth/templates/TwoFactorAuthSettings.html index 6414244f3..ba3dee0d1 100644 --- a/plugins/two-factor-auth/templates/TwoFactorAuthSettings.html +++ b/plugins/two-factor-auth/templates/TwoFactorAuthSettings.html @@ -1,109 +1,94 @@
-
+
-
- -
- 🔒 -   - +
+
+
+
+
+
+     + +
-
-
-
- -