Skip to content

Commit 82aec05

Browse files
[Security] Deprecate PersistentToken::getClass() and RememberMeDetails::getUserFqcn() in order to remove the user FQCN from the remember-me cookie in 8.0
1 parent 34c139d commit 82aec05

File tree

4 files changed

+20
-16
lines changed

4 files changed

+20
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* Deprecate `AbstractListener::__invoke`
1010
* Add `$methods` argument to `#[IsGranted]` to restrict validation to specific HTTP methods
1111
* Allow subclassing `#[IsGranted]`
12+
* Deprecate `RememberMeDetails::getUserFqcn()`, the user FQCN will be removed from the remember-me cookie in 8.0
1213

1314
7.3
1415
---

RememberMe/PersistentRememberMeHandler.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,51 +65,51 @@ public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): U
6565
}
6666

6767
[$series, $tokenValue] = explode(':', $rememberMeDetails->getValue(), 2);
68-
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
68+
$token = $this->tokenProvider->loadTokenBySeries($series);
6969

70-
if ($persistentToken->getUserIdentifier() !== $rememberMeDetails->getUserIdentifier() || $persistentToken->getClass() !== $rememberMeDetails->getUserFqcn()) {
70+
if ($token->getUserIdentifier() !== $rememberMeDetails->getUserIdentifier()) {
7171
throw new AuthenticationException('The cookie\'s hash is invalid.');
7272
}
7373

7474
// content of $rememberMeDetails is not trustable. this prevents use of this class
7575
unset($rememberMeDetails);
7676

7777
if ($this->tokenVerifier) {
78-
$isTokenValid = $this->tokenVerifier->verifyToken($persistentToken, $tokenValue);
78+
$isTokenValid = $this->tokenVerifier->verifyToken($token, $tokenValue);
7979
} else {
80-
$isTokenValid = hash_equals($persistentToken->getTokenValue(), $tokenValue);
80+
$isTokenValid = hash_equals($token->getTokenValue(), $tokenValue);
8181
}
8282
if (!$isTokenValid) {
8383
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
8484
}
8585

86-
$expires = $persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'];
86+
$expires = $token->getLastUsed()->getTimestamp() + $this->options['lifetime'];
8787
if ($expires < time()) {
8888
throw new AuthenticationException('The cookie has expired.');
8989
}
9090

9191
return parent::consumeRememberMeCookie(new RememberMeDetails(
92-
$persistentToken->getClass(),
93-
$persistentToken->getUserIdentifier(),
92+
method_exists($token, 'getClass') ? $token->getClass(false) : '',
93+
$token->getUserIdentifier(),
9494
$expires,
95-
$persistentToken->getLastUsed()->getTimestamp().':'.$series.':'.$tokenValue.':'.$persistentToken->getClass()
95+
$token->getLastUsed()->getTimestamp().':'.$series.':'.$tokenValue.':'.(method_exists($token, 'getClass') ? $token->getClass(false) : '')
9696
));
9797
}
9898

9999
public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInterface $user): void
100100
{
101101
[$lastUsed, $series, $tokenValue, $class] = explode(':', $rememberMeDetails->getValue(), 4);
102-
$persistentToken = new PersistentToken($class, $rememberMeDetails->getUserIdentifier(), $series, $tokenValue, new \DateTimeImmutable('@'.$lastUsed));
102+
$token = new PersistentToken($class, $rememberMeDetails->getUserIdentifier(), $series, $tokenValue, new \DateTimeImmutable('@'.$lastUsed));
103103

104104
// if a token was regenerated less than a minute ago, there is no need to regenerate it
105105
// if multiple concurrent requests reauthenticate a user we do not want to update the token several times
106-
if ($persistentToken->getLastUsed()->getTimestamp() + 60 >= time()) {
106+
if ($token->getLastUsed()->getTimestamp() + 60 >= time()) {
107107
return;
108108
}
109109

110110
$tokenValue = strtr(base64_encode(random_bytes(33)), '+/=', '-_~');
111111
$tokenLastUsed = new \DateTime();
112-
$this->tokenVerifier?->updateExistingToken($persistentToken, $tokenValue, $tokenLastUsed);
112+
$this->tokenVerifier?->updateExistingToken($token, $tokenValue, $tokenLastUsed);
113113
$this->tokenProvider->updateToken($series, $tokenValue, $tokenLastUsed);
114114

115115
$this->createCookie($rememberMeDetails->withValue($series.':'.$tokenValue));

RememberMe/RememberMeDetails.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ public static function fromRawCookie(string $rawCookie): self
4646
return new static(...$cookieParts);
4747
}
4848

49-
public static function fromPersistentToken(PersistentToken $persistentToken, int $expires): self
49+
public static function fromPersistentToken(PersistentToken $token, int $expires): self
5050
{
51-
return new static($persistentToken->getClass(), $persistentToken->getUserIdentifier(), $expires, $persistentToken->getSeries().':'.$persistentToken->getTokenValue());
51+
return new static(method_exists($token, 'getClass') ? $token->getClass(false) : '', $token->getUserIdentifier(), $expires, $token->getSeries().':'.$token->getTokenValue());
5252
}
5353

5454
public function withValue(string $value): self
@@ -59,8 +59,13 @@ public function withValue(string $value): self
5959
return $details;
6060
}
6161

62+
/**
63+
* @deprecated since Symfony 7.4, the user FQCN will be removed from the remember-me cookie in 8.0
64+
*/
6265
public function getUserFqcn(): string
6366
{
67+
trigger_deprecation('symfony/security-http', '7.4', 'The "%s()" method is deprecated: the user FQCN will be removed from the remember-me cookie in 8.0.', __METHOD__);
68+
6469
return $this->userFqcn;
6570
}
6671

Tests/RememberMe/PersistentRememberMeHandlerTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ public function testCreateRememberMeCookie()
5050
{
5151
$this->tokenProvider->expects($this->once())
5252
->method('createNewToken')
53-
->with($this->callback(fn ($persistentToken) => $persistentToken instanceof PersistentToken
54-
&& 'wouter' === $persistentToken->getUserIdentifier()
55-
&& InMemoryUser::class === $persistentToken->getClass()));
53+
->with($this->callback(fn ($token) => $token instanceof PersistentToken && 'wouter' === $token->getUserIdentifier()));
5654

5755
$this->handler->createRememberMeCookie(new InMemoryUser('wouter', null));
5856
}

0 commit comments

Comments
 (0)