Skip to content

Commit

Permalink
Don't require 2FA on administration action "Impersonate"
Browse files Browse the repository at this point in the history
yurabakhtin committed Aug 10, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 84a8759 commit a4c5a2a
Showing 4 changed files with 68 additions and 1 deletion.
34 changes: 34 additions & 0 deletions Events.php
Original file line number Diff line number Diff line change
@@ -8,9 +8,13 @@

namespace humhub\modules\twofa;

use humhub\components\Controller;
use humhub\modules\admin\controllers\UserController as AdminUserController;
use humhub\modules\admin\permissions\ManageUsers;
use humhub\modules\twofa\helpers\TwofaHelper;
use humhub\modules\twofa\helpers\TwofaUrl;
use humhub\modules\ui\menu\MenuLink;
use humhub\modules\user\controllers\AuthController;
use humhub\modules\user\events\UserEvent;
use humhub\modules\user\widgets\AccountMenu;
use Yii;
@@ -57,12 +61,42 @@ public static function onBeforeAction($event)
return false;
}

if (self::isImpersonateAction($event->sender)) {
Yii::$app->session->set('twofa.switchedUserId', Yii::$app->user->id);
}

if (TwofaHelper::isVerifyingRequired() &&
!Yii::$app->getModule('twofa')->isTwofaCheckUrl()) {
return Yii::$app->getResponse()->redirect(TwofaUrl::toCheck());
}
}

/**
* Check if currently action "Impersonate" is called
*
* @param $controller Controller
* @return bool
*/
protected static function isImpersonateAction(Controller $controller): bool
{
return ($controller instanceof AdminUserController) &&
isset($controller->action) &&
$controller->action->id == 'impersonate' &&
Yii::$app->user->can(ManageUsers::class);
}

/**
* Clear temp user ID which was used for administration action "Impersonate"
*
* @param $event
*/
public static function onAfterAction($event)
{
if ($event->sender instanceof AuthController && $event->sender->action->id == 'logout') {
Yii::$app->session->remove('twofa.switchedUserId');
}
}

/**
* Set flag after login to user who need 2fa
*
1 change: 1 addition & 0 deletions config.php
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
[Application::class, Application::EVENT_BEFORE_REQUEST, [Events::class, 'onBeforeRequest']],
[AuthController::class, AuthController::EVENT_AFTER_LOGIN, [Events::class, 'onAfterLogin']],
[Controller::class, Controller::EVENT_BEFORE_ACTION, [Events::class, 'onBeforeAction']],
[Controller::class, Controller::EVENT_AFTER_ACTION, [Events::class, 'onAfterAction']],
[AccountSettingsMenu::class, AccountSettingsMenu::EVENT_INIT, [Events::class, 'onProfileSettingMenuInit']],
],
];
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ Changelog
1.0.5 (Unreleased)
---------------------
- Fix #29: Fix button "Log out" to prevent pjax
- Fix #31: Don't require 2FA on administration action "Impersonate"

1.0.4 (15 June, 2021)
---------------------
33 changes: 32 additions & 1 deletion helpers/TwofaHelper.php
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@

namespace humhub\modules\twofa\helpers;

use humhub\modules\admin\Module as AdminModule;
use humhub\modules\content\components\ContentContainerSettingsManager;
use humhub\modules\twofa\drivers\BaseDriver;
use humhub\modules\twofa\Module as TwofaModule;
@@ -230,7 +231,37 @@ public static function disableVerifying()
*/
public static function isVerifyingRequired()
{
return self::getDriver() && self::getCode() !== null;
return !self::isImpersonateMode() && self::getDriver() && self::getCode() !== null;
}

/**
* Check if current User was logged in from administration action "Impersonate"
*
* @return bool
*/
protected static function isImpersonateMode(): bool
{
$switchedUserId = Yii::$app->session->get('twofa.switchedUserId');
if (empty($switchedUserId)) {
return false;
}

if (Yii::$app->user->isGuest) {
return false;
}

/* @var $adminModule AdminModule */
$adminModule = Yii::$app->getModule('admin');
if (!$adminModule->allowUserImpersonate) {
return false;
}

/* @var $switchedUser User */
if (!($switchedUser = User::findOne(['id' => $switchedUserId]))) {
return false;
}

return $switchedUser->id != Yii::$app->user->id;
}

/**

0 comments on commit a4c5a2a

Please sign in to comment.