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