@@ -53,6 +53,7 @@ protected function setUp(): void
53
53
54
54
/**
55
55
* @group time-sensitive
56
+ *
56
57
* @dataProvider provideCreateLoginLinkData
57
58
*/
58
59
public function testCreateLoginLink ($ user , array $ extraProperties , Request $ request = null )
@@ -68,7 +69,7 @@ public function testCreateLoginLink($user, array $extraProperties, Request $requ
68
69
// allow a small expiration offset to avoid time-sensitivity
69
70
&& abs (time () + 600 - $ parameters ['expires ' ]) <= 1
70
71
// make sure hash is what we expect
71
- && $ parameters ['hash ' ] === $ this ->createSignatureHash ('weaverryan ' , $ parameters ['expires ' ], array_values ( $ extraProperties) );
72
+ && $ parameters ['hash ' ] === $ this ->createSignatureHash ('weaverryan ' , $ parameters ['expires ' ], $ extraProperties );
72
73
}),
73
74
UrlGeneratorInterface::ABSOLUTE_URL
74
75
)
@@ -115,7 +116,7 @@ public function provideCreateLoginLinkData()
115
116
public function testConsumeLoginLink ()
116
117
{
117
118
$ expires = time () + 500 ;
118
- $ signature =
$ this ->
createSignatureHash (
'weaverryan ' ,
$ expires, [ ' [email protected] ' , ' pwhash ' ] );
119
+ $ signature = $ this ->createSignatureHash ('weaverryan ' , $ expires );
119
120
$ request = Request::create (sprintf ('/login/verify?user=weaverryan&hash=%s&expires=%d ' , $ signature , $ expires ));
120
121
121
122
$ user =
new TestLoginLinkHandlerUser (
'weaverryan ' ,
'[email protected] ' ,
'pwhash ' );
@@ -131,44 +132,37 @@ public function testConsumeLoginLink()
131
132
132
133
public function testConsumeLoginLinkWithExpired ()
133
134
{
134
- $ this ->expectException (ExpiredLoginLinkException::class);
135
135
$ expires = time () - 500 ;
136
- $ signature =
$ this ->
createSignatureHash (
'weaverryan ' ,
$ expires, [ ' [email protected] ' , ' pwhash ' ] );
136
+ $ signature = $ this ->createSignatureHash ('weaverryan ' , $ expires );
137
137
$ request = Request::create (sprintf ('/login/verify?user=weaverryan&hash=%s&expires=%d ' , $ signature , $ expires ));
138
138
139
- $ user =
new TestLoginLinkHandlerUser (
'weaverryan ' ,
'[email protected] ' ,
'pwhash ' );
140
- $ this ->userProvider ->createUser ($ user );
141
-
142
139
$ linker = $ this ->createLinker (['max_uses ' => 3 ]);
140
+ $ this ->expectException (ExpiredLoginLinkException::class);
143
141
$ linker ->consumeLoginLink ($ request );
144
142
}
145
143
146
144
public function testConsumeLoginLinkWithUserNotFound ()
147
145
{
148
- $ this ->expectException (InvalidLoginLinkException::class);
149
- $ request = Request::create ('/login/verify?user=weaverryan&hash=thehash&expires=10000 ' );
146
+ $ request = Request::create ('/login/verify?user=weaverryan&hash=thehash&expires= ' .(time () + 500 ));
150
147
151
148
$ linker = $ this ->createLinker ();
149
+ $ this ->expectException (InvalidLoginLinkException::class);
152
150
$ linker ->consumeLoginLink ($ request );
153
151
}
154
152
155
153
public function testConsumeLoginLinkWithDifferentSignature ()
156
154
{
157
- $ this ->expectException (InvalidLoginLinkException::class);
158
155
$ request = Request::create (sprintf ('/login/verify?user=weaverryan&hash=fake_hash&expires=%d ' , time () + 500 ));
159
156
160
- $ user =
new TestLoginLinkHandlerUser (
'weaverryan ' ,
'[email protected] ' ,
'pwhash ' );
161
- $ this ->userProvider ->createUser ($ user );
162
-
163
157
$ linker = $ this ->createLinker ();
158
+ $ this ->expectException (InvalidLoginLinkException::class);
164
159
$ linker ->consumeLoginLink ($ request );
165
160
}
166
161
167
162
public function testConsumeLoginLinkExceedsMaxUsage ()
168
163
{
169
- $ this ->expectException (ExpiredLoginLinkException::class);
170
164
$ expires = time () + 500 ;
171
- $ signature =
$ this ->
createSignatureHash (
'weaverryan ' ,
$ expires, [ ' [email protected] ' , ' pwhash ' ] );
165
+ $ signature = $ this ->createSignatureHash ('weaverryan ' , $ expires );
172
166
$ request = Request::create (sprintf ('/login/verify?user=weaverryan&hash=%s&expires=%d ' , $ signature , $ expires ));
173
167
174
168
$ user =
new TestLoginLinkHandlerUser (
'weaverryan ' ,
'[email protected] ' ,
'pwhash ' );
@@ -179,6 +173,7 @@ public function testConsumeLoginLinkExceedsMaxUsage()
179
173
$ this ->expiredLinkCache ->save ($ item );
180
174
181
175
$ linker = $ this ->createLinker (['max_uses ' => 3 ]);
176
+ $ this ->expectException (ExpiredLoginLinkException::class);
182
177
$ linker ->consumeLoginLink ($ request );
183
178
}
184
179
@@ -206,15 +201,12 @@ public function testConsumeLoginLinkWithMissingExpiration()
206
201
$ linker ->consumeLoginLink ($ request );
207
202
}
208
203
209
- private function createSignatureHash (string $ username , int $ expires , array $ extraFields ): string
204
+ private function createSignatureHash (
string $ username,
int $ expires,
array $ extraFields = [ ' emailProperty ' => ' [email protected] ' , ' passwordProperty ' => ' pwhash ' ] ):
string
210
205
{
211
- $ fields = [base64_encode ($ username ), $ expires ];
212
- foreach ($ extraFields as $ extraField ) {
213
- $ fields [] = base64_encode ($ extraField );
214
- }
206
+ $ hasher = new SignatureHasher ($ this ->propertyAccessor , array_keys ($ extraFields ), 's3cret ' );
207
+ $ user = new TestLoginLinkHandlerUser ($ username , $ extraFields ['emailProperty ' ] ?? '' , $ extraFields ['passwordProperty ' ] ?? '' , $ extraFields ['lastAuthenticatedAt ' ] ?? null );
215
208
216
- // matches hash logic in the class
217
- return base64_encode (hash_hmac ('sha256 ' , implode (': ' , $ fields ), 's3cret ' ));
209
+ return $ hasher ->computeSignatureHash ($ user , $ expires );
218
210
}
219
211
220
212
private function createLinker (array $ options = [], array $ extraProperties = ['emailProperty ' , 'passwordProperty ' ]): LoginLinkHandler
@@ -298,7 +290,7 @@ public function loadUserByIdentifier(string $userIdentifier): TestLoginLinkHandl
298
290
299
291
public function refreshUser (UserInterface $ user ): TestLoginLinkHandlerUser
300
292
{
301
- return $ this ->users [$ username ];
293
+ return $ this ->users [$ user -> getUserIdentifier () ];
302
294
}
303
295
304
296
public function supportsClass (string $ class ): bool
0 commit comments