15
15
use Symfony\Component\HttpFoundation\RequestStack;
16
16
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
17
17
use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
18
+ use Symfony\Component\Security\Core\Authentication\RememberMe\TokenVerifierInterface;
18
19
use Symfony\Component\Security\Core\Exception\AuthenticationException;
19
20
use Symfony\Component\Security\Core\Exception\CookieTheftException;
20
21
use Symfony\Component\Security\Core\User\UserInterface;
32
33
final class PersistentRememberMeHandler extends AbstractRememberMeHandler
33
34
{
34
35
private $tokenProvider;
36
+ private $tokenVerifier;
35
37
private $secret;
36
38
37
- public function __construct(TokenProviderInterface $tokenProvider, string $secret, UserProviderInterface $userProvider, RequestStack $requestStack, array $options, ?LoggerInterface $logger = null)
39
+ public function __construct(TokenProviderInterface $tokenProvider, string $secret, UserProviderInterface $userProvider, RequestStack $requestStack, array $options, ?LoggerInterface $logger = null, ?TokenVerifierInterface $tokenVerifier = null )
38
40
{
39
41
parent::__construct($userProvider, $requestStack, $options, $logger);
40
42
43
+ if (!$tokenVerifier && $tokenProvider instanceof TokenVerifierInterface) {
44
+ $tokenVerifier = $tokenProvider;
45
+ }
41
46
$this->tokenProvider = $tokenProvider;
47
+ $this->tokenVerifier = $tokenVerifier;
42
48
$this->secret = $secret;
43
49
}
44
50
@@ -66,7 +72,13 @@ public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInte
66
72
67
73
[$series, $tokenValue] = explode(':', $rememberMeDetails->getValue());
68
74
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
69
- if (!hash_equals($persistentToken->getTokenValue(), $tokenValue)) {
75
+
76
+ if ($this->tokenVerifier) {
77
+ $isTokenValid = $this->tokenVerifier->verifyToken($persistentToken, $tokenValue);
78
+ } else {
79
+ $isTokenValid = hash_equals($persistentToken->getTokenValue(), $tokenValue);
80
+ }
81
+ if (!$isTokenValid) {
70
82
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
71
83
}
72
84
@@ -78,7 +90,12 @@ public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInte
78
90
// if multiple concurrent requests reauthenticate a user we do not want to update the token several times
79
91
if ($persistentToken->getLastUsed()->getTimestamp() + 60 < time()) {
80
92
$tokenValue = base64_encode(random_bytes(64));
81
- $this->tokenProvider->updateToken($series, $this->generateHash($tokenValue), new \DateTime());
93
+ $tokenValueHash = $this->generateHash($tokenValue);
94
+ $tokenLastUsed = new \DateTime();
95
+ if ($this->tokenVerifier) {
96
+ $this->tokenVerifier->updateExistingToken($persistentToken, $tokenValueHash, $tokenLastUsed);
97
+ }
98
+ $this->tokenProvider->updateToken($series, $tokenValueHash, $tokenLastUsed);
82
99
}
83
100
84
101
$this->createCookie($rememberMeDetails->withValue($tokenValue));
0 commit comments