Skip to content

Commit 07de038

Browse files
wouterjfabpot
authored andcommitted
[Security] Fix UsageTrackingTokenStorage outside the request cycle
1 parent d857e32 commit 07de038

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

Authentication/Token/Storage/UsageTrackingTokenStorage.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function __construct(TokenStorageInterface $storage, ContainerInterface $
3939
*/
4040
public function getToken(): ?TokenInterface
4141
{
42-
if ($this->enableUsageTracking) {
42+
if ($this->shouldTrackUsage()) {
4343
// increments the internal session usage index
4444
$this->getSession()->getMetadataBag();
4545
}
@@ -54,7 +54,7 @@ public function setToken(TokenInterface $token = null): void
5454
{
5555
$this->storage->setToken($token);
5656

57-
if ($token && $this->enableUsageTracking) {
57+
if ($token && $this->shouldTrackUsage()) {
5858
// increments the internal session usage index
5959
$this->getSession()->getMetadataBag();
6060
}
@@ -88,4 +88,24 @@ private function getSession(): SessionInterface
8888

8989
return $this->container->get('request_stack')->getSession();
9090
}
91+
92+
private function shouldTrackUsage(): bool
93+
{
94+
if (!$this->enableUsageTracking) {
95+
return false;
96+
}
97+
98+
// BC for symfony/security-bundle < 5.3
99+
if ($this->container->has('session')) {
100+
return true;
101+
}
102+
103+
if (!$this->container->get('request_stack')->getMainRequest()) {
104+
trigger_deprecation('symfony/security-core', '5.3', 'Using "%s" (service ID: "security.token_storage") outside the request-response cycle is deprecated, use the "%s" class (service ID: "security.untracked_token_storage") instead or disable usage tracking using "disableUsageTracking()".', __CLASS__, TokenStorage::class);
105+
106+
return false;
107+
}
108+
109+
return true;
110+
}
91111
}

Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,37 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Psr\Container\ContainerInterface;
16+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
1617
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpFoundation\RequestStack;
1819
use Symfony\Component\HttpFoundation\Session\SessionInterface;
1920
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
2021
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
2122
use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage;
22-
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
2323
use Symfony\Contracts\Service\ServiceLocatorTrait;
2424

2525
class UsageTrackingTokenStorageTest extends TestCase
2626
{
27+
use ExpectDeprecationTrait;
28+
2729
public function testGetSetToken()
2830
{
2931
$sessionAccess = 0;
3032
$sessionLocator = new class(['request_stack' => function () use (&$sessionAccess) {
31-
++$sessionAccess;
32-
3333
$session = $this->createMock(SessionInterface::class);
34-
$session->expects($this->once())
35-
->method('getMetadataBag');
3634

3735
$request = new Request();
3836
$request->setSession($session);
39-
$requestStack = new RequestStack();
37+
$requestStack = $this->getMockBuilder(RequestStack::class)->setMethods(['getSession'])->getMock();
4038
$requestStack->push($request);
39+
$requestStack->expects($this->any())->method('getSession')->willReturnCallback(function () use ($session, &$sessionAccess) {
40+
++$sessionAccess;
41+
42+
$session->expects($this->once())
43+
->method('getMetadataBag');
44+
45+
return $session;
46+
});
4147

4248
return $requestStack;
4349
}]) implements ContainerInterface {
@@ -62,4 +68,22 @@ public function testGetSetToken()
6268
$this->assertSame($token, $trackingStorage->getToken());
6369
$this->assertSame(1, $sessionAccess);
6470
}
71+
72+
/**
73+
* @group legacy
74+
*/
75+
public function testWithoutMainRequest()
76+
{
77+
$locator = new class(['request_stack' => function () {
78+
return new RequestStack();
79+
}]) implements ContainerInterface {
80+
use ServiceLocatorTrait;
81+
};
82+
$tokenStorage = new TokenStorage();
83+
$trackingStorage = new UsageTrackingTokenStorage($tokenStorage, $locator);
84+
$trackingStorage->enableUsageTracking();
85+
86+
$this->expectDeprecation('Since symfony/security-core 5.3: Using "%s" (service ID: "security.token_storage") outside the request-response cycle is deprecated, use the "%s" class (service ID: "security.untracked_token_storage") instead or disable usage tracking using "disableUsageTracking()".');
87+
$trackingStorage->getToken();
88+
}
6589
}

0 commit comments

Comments
 (0)