1515use Symfony \Component \HttpFoundation \RequestStack ;
1616use Symfony \Component \Security \Core \Authentication \RememberMe \PersistentToken ;
1717use Symfony \Component \Security \Core \Authentication \RememberMe \TokenProviderInterface ;
18+ use Symfony \Component \Security \Core \Authentication \RememberMe \TokenVerifierInterface ;
1819use Symfony \Component \Security \Core \Exception \AuthenticationException ;
1920use Symfony \Component \Security \Core \Exception \CookieTheftException ;
2021use Symfony \Component \Security \Core \User \UserInterface ;
3233final class PersistentRememberMeHandler extends AbstractRememberMeHandler
3334{
3435 private $ tokenProvider ;
36+ private $ tokenVerifier ;
3537 private $ secret ;
3638
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 )
3840 {
3941 parent ::__construct ($ userProvider , $ requestStack , $ options , $ logger );
4042
43+ if (!$ tokenVerifier && $ tokenProvider instanceof TokenVerifierInterface) {
44+ $ tokenVerifier = $ tokenProvider ;
45+ }
4146 $ this ->tokenProvider = $ tokenProvider ;
47+ $ this ->tokenVerifier = $ tokenVerifier ;
4248 $ this ->secret = $ secret ;
4349 }
4450
@@ -66,7 +72,13 @@ public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInte
6672
6773 [$ series , $ tokenValue ] = explode (': ' , $ rememberMeDetails ->getValue ());
6874 $ 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 ) {
7082 throw new CookieTheftException ('This token was already used. The account is possibly compromised. ' );
7183 }
7284
@@ -78,7 +90,12 @@ public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInte
7890 // if multiple concurrent requests reauthenticate a user we do not want to update the token several times
7991 if ($ persistentToken ->getLastUsed ()->getTimestamp () + 60 < time ()) {
8092 $ 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 );
8299 }
83100
84101 $ this ->createCookie ($ rememberMeDetails ->withValue ($ tokenValue ));
0 commit comments