Skip to content

Commit 0b78cbb

Browse files
committed
Invalidate user sessions and handle expired users on login (#22833)
1 parent 8b5bec6 commit 0b78cbb

File tree

5 files changed

+84
-24
lines changed

5 files changed

+84
-24
lines changed

app/code/Magento/Security/Model/AdminSessionsManager.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class AdminSessionsManager
2727
*/
2828
const LOGOUT_REASON_USER_LOCKED = 10;
2929

30+
/**
31+
* User has been logged out due to an expired user account
32+
*/
33+
const LOGOUT_REASON_USER_EXPIRED = 11;
34+
3035
/**
3136
* @var ConfigInterface
3237
* @since 100.1.0
@@ -100,7 +105,7 @@ public function __construct(
100105
}
101106

102107
/**
103-
* Handle all others active sessions according Sharing Account Setting
108+
* Handle all others active sessions according Sharing Account Setting and expired users.
104109
*
105110
* @return $this
106111
* @since 100.1.0
@@ -122,6 +127,11 @@ public function processLogin()
122127
}
123128
}
124129

130+
if ($this->authSession->getUser()->getExpiresAt())
131+
{
132+
$this->revokeExpiredAdminUser();
133+
}
134+
125135
return $this;
126136
}
127137

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

157+
if ($this->authSession->getUser()->getExpiresAt())
158+
{
159+
$this->revokeExpiredAdminUser();
160+
}
161+
147162
return $this;
148163
}
149164

@@ -209,6 +224,11 @@ public function getLogoutReasonMessageByStatus($statusCode)
209224
'Your account is temporarily disabled. Please try again later.'
210225
);
211226
break;
227+
case self::LOGOUT_REASON_USER_EXPIRED:
228+
$reasonMessage = __(
229+
'Your account has expired.'
230+
);
231+
break;
212232
default:
213233
$reasonMessage = __('Your current session has been expired.');
214234
break;
@@ -353,4 +373,21 @@ private function getIntervalBetweenConsecutiveProlongs()
353373
)
354374
);
355375
}
376+
377+
/**
378+
* Check if the current user is expired and, if so, revoke their admin token.
379+
*/
380+
private function revokeExpiredAdminUser()
381+
{
382+
$expiresAt = $this->dateTime->gmtTimestamp($this->authSession->getUser()->getExpiresAt());
383+
if ($expiresAt < $this->dateTime->gmtTimestamp()) {
384+
$currentSessions = $this->getSessionsForCurrentUser();
385+
$currentSessions->setDataToAll('status', self::LOGOUT_REASON_USER_EXPIRED)
386+
->save();
387+
$this->authSession->getUser()
388+
->setIsActive(0)
389+
->setExpiresAt(null)
390+
->save();
391+
}
392+
}
356393
}

app/code/Magento/User/Cron/DisableExpiredUsers.php

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace Magento\User\Cron;
88

9+
use Magento\Security\Model\AdminSessionsManager;
10+
911
/**
1012
* Disable expired users.
1113
*/
@@ -15,33 +17,53 @@ class DisableExpiredUsers
1517
/**
1618
* @var \Magento\User\Model\ResourceModel\User\CollectionFactory
1719
*/
18-
private $collectionFactory;
20+
private $userCollectionFactory;
21+
/**
22+
* @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory
23+
*/
24+
private $adminSessionCollectionFactory;
25+
/**
26+
* @var \Magento\Security\Model\ConfigInterface
27+
*/
28+
private $securityConfig;
1929

2030
/**
21-
* @param \Magento\User\Model\ResourceModel\User\CollectionFactory $collectionFactory
31+
* @param \Magento\User\Model\ResourceModel\User\CollectionFactory $userCollectionFactory
32+
* @param \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory $adminSessionCollectionFactory
33+
* @param \Magento\Security\Model\ConfigInterface $securityConfig
2234
*/
2335
public function __construct(
24-
\Magento\User\Model\ResourceModel\User\CollectionFactory $collectionFactory
36+
\Magento\User\Model\ResourceModel\User\CollectionFactory $userCollectionFactory,
37+
\Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory $adminSessionCollectionFactory,
38+
\Magento\Security\Model\ConfigInterface $securityConfig
2539
) {
26-
$this->collectionFactory = $collectionFactory;
40+
$this->userCollectionFactory = $userCollectionFactory;
41+
$this->adminSessionCollectionFactory = $adminSessionCollectionFactory;
42+
$this->securityConfig = $securityConfig;
2743
}
2844

2945
/**
30-
* Disable all expired user accounts.
31-
* TODO: add plugin to authentication to disable since not everyone
32-
* has cron running (see \Magento\Security\Model\AdminSessionsManager::processLogin?)
46+
* Disable all expired user accounts and invalidate their sessions.
3347
*/
3448
public function execute()
3549
{
36-
$users = $this->collectionFactory->create()
37-
->addExpiresAtFilter()
38-
->addFieldToFilter('is_active', 1)
39-
;
40-
/** @var \Magento\User\Model\User $user */
41-
foreach ($users as $user) {
42-
$user->setIsActive(0)
43-
->setExpiresAt(null)
50+
/** @var \Magento\User\Model\ResourceModel\User\Collection $users */
51+
$users = $this->userCollectionFactory->create()
52+
->addActiveExpiredUsersFilter();
53+
54+
if ($users->getSize() > 0)
55+
{
56+
/** @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\Collection $currentSessions */
57+
$currentSessions = $this->adminSessionCollectionFactory->create()
58+
->addFieldToFilter('user_id', ['in' => $users->getAllIds()])
59+
->addFieldToFilter('status', \Magento\Security\Model\AdminSessionInfo::LOGGED_IN)
60+
->filterExpiredSessions($this->securityConfig->getAdminSessionLifetime());
61+
$currentSessions->setDataToAll('status', AdminSessionsManager::LOGOUT_REASON_USER_EXPIRED)
4462
->save();
4563
}
64+
65+
$users->setDataToAll('expires_at', null)
66+
->setDataToAll('is_active', 0)
67+
->save();
4668
}
4769
}

app/code/Magento/User/Model/ResourceModel/User/Collection.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,18 @@ protected function _initSelect()
4343
}
4444

4545
/**
46-
* Filter users by expires_at.
47-
* @param string|null $now
46+
* Filter for expired, active users.
47+
* @param null $now
4848
* @return $this
4949
*/
50-
public function addExpiresAtFilter($now = null)
50+
public function addActiveExpiredUsersFilter($now = null)
5151
{
5252
if ($now === null) {
5353
$now = new \DateTime();
5454
$now->format('Y-m-d H:i:s');
5555
}
56-
57-
$this->addFieldToFilter('expires_at', ['lt' => $now]);
56+
$this->addFieldToFilter('expires_at', ['lt' => $now])
57+
->addFieldToFilter('is_active', 1);
5858

5959
return $this;
6060
}

dev/tests/integration/testsuite/Magento/User/Cron/DisableExpiredUsersTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Magento\TestFramework\Helper\Bootstrap;
1010

1111
/**
12+
* TODO: test logging out sessions
1213
* @magentoAppArea adminhtml
1314
*/
1415
class DisableExpiredUsersTest extends \PHPUnit\Framework\TestCase

dev/tests/integration/testsuite/Magento/User/Model/ResourceModel/User/CollectionTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ public function testSelectQueryInitialized()
3535
/**
3636
* @magentoDataFixture Magento/User/_files/expired_users.php
3737
*/
38-
public function testExpiresAtFilter()
38+
public function testExpiredActiveUsersFilter()
3939
{
40-
$this->collection->addExpiresAtFilter();
41-
static::assertCount(1, $this->collection);
40+
$this->collection->addActiveExpiredUsersFilter();
41+
static::assertGreaterThan(1, $this->collection->getSize());
4242
}
4343
}

0 commit comments

Comments
 (0)