Skip to content

Commit

Permalink
Invalidate user sessions and handle expired users on login (#22833)
Browse files Browse the repository at this point in the history
  • Loading branch information
lfolco committed May 19, 2019
1 parent 8b5bec6 commit 0b78cbb
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 24 deletions.
39 changes: 38 additions & 1 deletion app/code/Magento/Security/Model/AdminSessionsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class AdminSessionsManager
*/
const LOGOUT_REASON_USER_LOCKED = 10;

/**
* User has been logged out due to an expired user account
*/
const LOGOUT_REASON_USER_EXPIRED = 11;

/**
* @var ConfigInterface
* @since 100.1.0
Expand Down Expand Up @@ -100,7 +105,7 @@ public function __construct(
}

/**
* Handle all others active sessions according Sharing Account Setting
* Handle all others active sessions according Sharing Account Setting and expired users.
*
* @return $this
* @since 100.1.0
Expand All @@ -122,6 +127,11 @@ public function processLogin()
}
}

if ($this->authSession->getUser()->getExpiresAt())
{
$this->revokeExpiredAdminUser();
}

return $this;
}

Expand All @@ -144,6 +154,11 @@ public function processProlong()
$this->getCurrentSession()->save();
}

if ($this->authSession->getUser()->getExpiresAt())
{
$this->revokeExpiredAdminUser();
}

return $this;
}

Expand Down Expand Up @@ -209,6 +224,11 @@ public function getLogoutReasonMessageByStatus($statusCode)
'Your account is temporarily disabled. Please try again later.'
);
break;
case self::LOGOUT_REASON_USER_EXPIRED:
$reasonMessage = __(
'Your account has expired.'
);
break;
default:
$reasonMessage = __('Your current session has been expired.');
break;
Expand Down Expand Up @@ -353,4 +373,21 @@ private function getIntervalBetweenConsecutiveProlongs()
)
);
}

/**
* Check if the current user is expired and, if so, revoke their admin token.
*/
private function revokeExpiredAdminUser()
{
$expiresAt = $this->dateTime->gmtTimestamp($this->authSession->getUser()->getExpiresAt());
if ($expiresAt < $this->dateTime->gmtTimestamp()) {
$currentSessions = $this->getSessionsForCurrentUser();
$currentSessions->setDataToAll('status', self::LOGOUT_REASON_USER_EXPIRED)
->save();
$this->authSession->getUser()
->setIsActive(0)
->setExpiresAt(null)
->save();
}
}
}
52 changes: 37 additions & 15 deletions app/code/Magento/User/Cron/DisableExpiredUsers.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

namespace Magento\User\Cron;

use Magento\Security\Model\AdminSessionsManager;

/**
* Disable expired users.
*/
Expand All @@ -15,33 +17,53 @@ class DisableExpiredUsers
/**
* @var \Magento\User\Model\ResourceModel\User\CollectionFactory
*/
private $collectionFactory;
private $userCollectionFactory;
/**
* @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory
*/
private $adminSessionCollectionFactory;
/**
* @var \Magento\Security\Model\ConfigInterface
*/
private $securityConfig;

/**
* @param \Magento\User\Model\ResourceModel\User\CollectionFactory $collectionFactory
* @param \Magento\User\Model\ResourceModel\User\CollectionFactory $userCollectionFactory
* @param \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory $adminSessionCollectionFactory
* @param \Magento\Security\Model\ConfigInterface $securityConfig
*/
public function __construct(
\Magento\User\Model\ResourceModel\User\CollectionFactory $collectionFactory
\Magento\User\Model\ResourceModel\User\CollectionFactory $userCollectionFactory,
\Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory $adminSessionCollectionFactory,
\Magento\Security\Model\ConfigInterface $securityConfig
) {
$this->collectionFactory = $collectionFactory;
$this->userCollectionFactory = $userCollectionFactory;
$this->adminSessionCollectionFactory = $adminSessionCollectionFactory;
$this->securityConfig = $securityConfig;
}

/**
* Disable all expired user accounts.
* TODO: add plugin to authentication to disable since not everyone
* has cron running (see \Magento\Security\Model\AdminSessionsManager::processLogin?)
* Disable all expired user accounts and invalidate their sessions.
*/
public function execute()
{
$users = $this->collectionFactory->create()
->addExpiresAtFilter()
->addFieldToFilter('is_active', 1)
;
/** @var \Magento\User\Model\User $user */
foreach ($users as $user) {
$user->setIsActive(0)
->setExpiresAt(null)
/** @var \Magento\User\Model\ResourceModel\User\Collection $users */
$users = $this->userCollectionFactory->create()
->addActiveExpiredUsersFilter();

if ($users->getSize() > 0)
{
/** @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\Collection $currentSessions */
$currentSessions = $this->adminSessionCollectionFactory->create()
->addFieldToFilter('user_id', ['in' => $users->getAllIds()])
->addFieldToFilter('status', \Magento\Security\Model\AdminSessionInfo::LOGGED_IN)
->filterExpiredSessions($this->securityConfig->getAdminSessionLifetime());
$currentSessions->setDataToAll('status', AdminSessionsManager::LOGOUT_REASON_USER_EXPIRED)
->save();
}

$users->setDataToAll('expires_at', null)
->setDataToAll('is_active', 0)
->save();
}
}
10 changes: 5 additions & 5 deletions app/code/Magento/User/Model/ResourceModel/User/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ protected function _initSelect()
}

/**
* Filter users by expires_at.
* @param string|null $now
* Filter for expired, active users.
* @param null $now
* @return $this
*/
public function addExpiresAtFilter($now = null)
public function addActiveExpiredUsersFilter($now = null)
{
if ($now === null) {
$now = new \DateTime();
$now->format('Y-m-d H:i:s');
}

$this->addFieldToFilter('expires_at', ['lt' => $now]);
$this->addFieldToFilter('expires_at', ['lt' => $now])
->addFieldToFilter('is_active', 1);

return $this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Magento\TestFramework\Helper\Bootstrap;

/**
* TODO: test logging out sessions
* @magentoAppArea adminhtml
*/
class DisableExpiredUsersTest extends \PHPUnit\Framework\TestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public function testSelectQueryInitialized()
/**
* @magentoDataFixture Magento/User/_files/expired_users.php
*/
public function testExpiresAtFilter()
public function testExpiredActiveUsersFilter()
{
$this->collection->addExpiresAtFilter();
static::assertCount(1, $this->collection);
$this->collection->addActiveExpiredUsersFilter();
static::assertGreaterThan(1, $this->collection->getSize());
}
}

0 comments on commit 0b78cbb

Please sign in to comment.