Skip to content

Commit b6139cc

Browse files
fix: make TrustedDeviceTokenStorage conform to ResetInterface (#266)
* Make TrustedDeviceTokenStorage conform to ResetInterface In certain scenarios, TrustedDeviceTokenStorage might not be re-instanciated between requests. That's the case when multiple requests are handled by a single worker, like when serving the application with RoadRunner or with FrankenPHP. In that case, the trusted_device cookie leak from a request to another, and break the feature entirely. By implementing ResetInterface, the storage is now properly reseted between requests
1 parent e4bf04e commit b6139cc

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"symfony/http-kernel": "^6.4 || ^7.0",
2626
"symfony/property-access": "^6.4 || ^7.0",
2727
"symfony/security-bundle": "^6.4 || ^7.0",
28+
"symfony/service-contracts": "^2.5|^3",
2829
"symfony/twig-bundle": "^6.4 || ^7.0"
2930
},
3031
"require-dev": {

src/bundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"symfony/http-kernel": "^6.4 || ^7.0",
2323
"symfony/property-access": "^6.4 || ^7.0",
2424
"symfony/security-bundle": "^6.4 || ^7.0",
25+
"symfony/service-contracts": "^2.5|^3",
2526
"symfony/twig-bundle": "^6.4 || ^7.0"
2627
},
2728
"autoload": {

src/trusted-device/Security/TwoFactor/Trusted/TrustedDeviceTokenStorage.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
use RuntimeException;
88
use Symfony\Component\HttpFoundation\Request;
99
use Symfony\Component\HttpFoundation\RequestStack;
10+
use Symfony\Contracts\Service\ResetInterface;
1011
use function array_map;
1112
use function explode;
1213
use function implode;
1314

1415
/**
1516
* @final
1617
*/
17-
class TrustedDeviceTokenStorage
18+
class TrustedDeviceTokenStorage implements ResetInterface
1819
{
1920
private const TOKEN_DELIMITER = ';';
2021

@@ -100,6 +101,12 @@ public function clearTrustedToken(string $username, string $firewall): void
100101
$this->updateCookie = true;
101102
}
102103

104+
public function reset(): void
105+
{
106+
$this->updateCookie = false;
107+
$this->trustedTokenList = null;
108+
}
109+
103110
/**
104111
* @return TrustedDeviceToken[]
105112
*/

tests/Security/TwoFactor/Trusted/TrustedDeviceTokenStorageTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,4 +337,32 @@ public function getCookieValue_hasTokenCalledWithInvalidToken_returnSerializedWi
337337
$returnValue = $this->tokenStorage->getCookieValue();
338338
$this->assertEquals('validToken', $returnValue);
339339
}
340+
341+
/**
342+
* @test
343+
*/
344+
public function reset_cookiePreviouslyUpdated_resetUpdatedCookie(): void
345+
{
346+
$this->tokenStorage->addTrustedToken('username', 'firewallName', 1);
347+
$this->assertTrue($this->tokenStorage->hasUpdatedCookie());
348+
349+
$this->tokenStorage->reset();
350+
$this->assertFalse($this->tokenStorage->hasUpdatedCookie());
351+
}
352+
353+
/**
354+
* @test
355+
*/
356+
public function reset_cookiePreviouslyUpdated_resetCookieList(): void
357+
{
358+
$this->stubCookieHasToken('serializedToken');
359+
$this->stubDecodeToken(
360+
$this->createTokenWithProperties('serializedToken', true, true, false),
361+
);
362+
$this->assertEquals('serializedToken', $this->tokenStorage->getCookieValue());
363+
364+
$this->request->cookies->remove('cookieName');
365+
$this->tokenStorage->reset();
366+
$this->assertEmpty($this->tokenStorage->getCookieValue());
367+
}
340368
}

0 commit comments

Comments
 (0)