8000 feature #40785 [Security] Deprecate using UsageTrackingTokenStorage o… · symfony/symfony@64cc548 · GitHub
[go: up one dir, main page]

Skip to content

Commit 64cc548

Browse files
committed
feature #40785 [Security] Deprecate using UsageTrackingTokenStorage outside the request-response cycle (wouterj)
This PR was merged into the 5.3-dev branch. Discussion ---------- [Security] Deprecate using UsageTrackingTokenStorage outside the request-response cycle | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | yes | New feature? | no | Deprecations? | yes | Tickets | Fix #40778 | License | MIT | Doc PR | - Currently, you get an "There is currently no session available" exception when using the `security.token_storage` service outside the main request-response cycle (e.g. in a `kernel.terminate` listener). This PR deprecates such usage and requires developers to update their definitions to explicitly use `security.untracked_token_storage` instead. A different solution would be to silently disable tracking in these cases, but I think that might create some unnecessary technical debt. Commits ------- 7452476 [Security] Fix UsageTrackingTokenStorage outside the request cycle
2 parents 40b4ff8 + 7452476 commit 64cc548

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

UPGRADE-5.3.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ Routing
102102
Security
103103
--------
104104

105+
* Deprecate using `UsageTrackingTokenStorage` with tracking enabled without a main request. Use the untracked token
106+
storage (service ID: `security.untracked_token_storage`) instead, or disable usage tracking
107+
completely using `UsageTrackingTokenStorage::disableUsageTracking()`.
105108
* [BC BREAK] Remove method `checkIfCompletelyResolved()` from `PassportInterface`, checking that passport badges are
106109
resolved is up to `AuthenticatorManager`
107110
* Deprecate class `User`, use `InMemoryUser` or your own implementation instead.

src/Symfony/Component/Security/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ CHANGELOG
2424
* Add `LegacyPasswordAuthenticatedUserInterface` for user classes that use user-provided salts in addition to passwords
2525
* Deprecate all classes in the `Core\Encoder\` sub-namespace, use the `PasswordHasher` component instead
2626
* Deprecate the `SessionInterface $session` constructor argument of `SessionTokenStorage`, inject a `\Symfony\Component\HttpFoundation\RequestStack $requestStack` instead
27+
* Deprecate using `UsageTrackingTokenStorage` without a main request
2728
* Deprecate the `session` service provided by the ServiceLocator injected in `UsageTrackingTokenStorage`, provide a `request_stack` service instead
2829
* Deprecate using `SessionTokenStorage` outside a request context, it will throw a `SessionNotFoundException` in Symfony 6.0
2930
* Randomize CSRF tokens to harden BREACH attacks

src/Symfony/Component/Security/Core/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+
9 8000 8+
// 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
}

src/Symfony/Component/Security/Core/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)
0