24
24
use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorage ;
25
25
use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorageInterface ;
26
26
use Symfony \Component \Security \Core \Security ;
27
+ use Symfony \Component \Security \Csrf \CsrfTokenManagerInterface ;
27
28
use Symfony \Component \Security \Http \Authentication \AuthenticationFailureHandlerInterface ;
28
29
use Symfony \Component \Security \Http \Authentication \DefaultAuthenticationFailureHandler ;
29
30
use Symfony \Component \Security \Http \Authentication \DefaultAuthenticationSuccessHandler ;
@@ -40,7 +41,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
40
41
/**
41
42
* @dataProvider getUsernameForLength
42
43
*/
43
- public function testHandleWhenUsernameLength ($ username , $ ok )
44
+ public function testHandleWhenUsernameLength (string $ username , bool $ ok )
44
45
{
45
46
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => $ username , '_password ' => 'symfony ' ]);
46
47
$ request ->setSession ($ this ->createMock (SessionInterface::class));
@@ -87,10 +88,8 @@ public function testHandleWhenUsernameLength($username, $ok)
87
88
/**
88
89
* @dataProvider postOnlyDataProvider
89
90
*/
90
- public function testHandleNonStringUsernameWithArray ($ postOnly )
91
+ public function testHandleNonStringUsernameWithArray (bool $ postOnly )
91
92
{
92
- $ this ->expectException (BadRequestHttpException::class);
93
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
94
93
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => []]);
95
94
$ request ->setSession ($ this ->createMock (SessionInterface::class));
96
95
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -104,16 +103,18 @@ public function testHandleNonStringUsernameWithArray($postOnly)
104
103
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
105
104
);
106
105
$ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
106
+
107
+ $ this ->expectException (BadRequestHttpException::class);
108
+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
109
+
107
110
$ listener ($ event );
108
111
}
109
112
110
113
/**
111
114
* @dataProvider postOnlyDataProvider
112
115
*/
113
- public function testHandleNonStringUsernameWithInt ($ postOnly )
116
+ public function testHandleNonStringUsernameWithInt (bool $ postOnly )
114
117
{
115
- $ this ->expectException (BadRequestHttpException::class);
116
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "int" given. ' );
117
118
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => 42 ]);
118
119
$ request ->setSession ($ this ->createMock (SessionInterface::class));
119
120
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -127,16 +128,18 @@ public function testHandleNonStringUsernameWithInt($postOnly)
127
128
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
128
129
);
129
130
$ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
131
+
132
+ $ this ->expectException (BadRequestHttpException::class);
133
+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "int" given. ' );
134
+
130
135
$ listener ($ event );
131
136
}
132
137
133
138
/**
134
139
* @dataProvider postOnlyDataProvider
135
140
*/
136
- public function testHandleNonStringUsernameWithObject ($ postOnly )
141
+ public function testHandleNonStringUsernameWithObject (bool $ postOnly )
137
142
{
138
- $ this ->expectException (BadRequestHttpException::class);
139
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "stdClass" given. ' );
140
143
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => new \stdClass ()]);
141
144
$ request ->setSession ($ this ->createMock (SessionInterface::class));
142
145
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -150,13 +153,17 @@ public function testHandleNonStringUsernameWithObject($postOnly)
150
153
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
151
154
);
152
155
$ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
156
+
157
+ $ this ->expectException (BadRequestHttpException::class);
158
+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "stdClass" given. ' );
159
+
153
160
$ listener ($ event );
154
161
}
155
162
156
163
/**
157
164
* @dataProvider postOnlyDataProvider
158
165
*/
159
- public function testHandleNonStringUsernameWith__toString ($ postOnly )
166
+ public function testHandleNonStringUsernameWith__toString (bool $ postOnly )
160
167
{
161
168
$ usernameClass = $ this ->createMock (DummyUserClass::class);
162
169
$ usernameClass
@@ -204,21 +211,86 @@ public function testHandleWhenPasswordAreNull($postOnly)
204
211
$ listener ($ event );
205
212
}
206
213
207
- public function postOnlyDataProvider ()
214
+ /**
215
+ * @dataProvider provideInvalidCsrfTokens
216
+ */
217
+ public function testInvalidCsrfToken ($ invalidToken )
218
+ {
219
+ $ formBody = ['_username ' => 'fabien ' , '_password ' => 'symfony ' ];
220
+ if (null !== $ invalidToken ) {
221
+ $ formBody ['_csrf_token ' ] = $ invalidToken ;
222
+ }
223
+
224
+ $ request = Request::create ('/login_check ' , 'POST ' , $ formBody );
225
+ $ request ->setSession ($ this ->createMock (SessionInterface::class));
226
+
227
+ $ httpUtils = $ this ->createMock (HttpUtils::class);
228
+ $ httpUtils
229
+ ->method ('checkRequestPath ' )
230
+ ->willReturn (true )
231
+ ;
232
+ $ httpUtils
233
+ ->method ('createRedirectResponse ' )
234
+ ->willReturn (new RedirectResponse ('/hello ' ))
235
+ ;
236
+
237
+ $ failureHandler = $ this ->createMock (AuthenticationFailureHandlerInterface::class);
238
+ $ failureHandler
239
+ ->expects ($ this ->once ())
240
+ ->method ('onAuthenticationFailure ' )
241
+ ->willReturn (new Response ())
242
+ ;
243
+
244
+ $ authenticationManager = $ this ->createMock (AuthenticationProviderManager::class);
245
+ $ authenticationManager
246
+ ->expects ($ this ->never ())
247
+ ->method ('authenticate ' )
248
+ ;
249
+
250
+ $ csrfTokenManager = $ this ->createMock (CsrfTokenManagerInterface::class);
251
+ $ csrfTokenManager ->method ('isTokenValid ' )->willReturn (false );
252
+
253
+ $ listener = new UsernamePasswordFormAuthenticationListener (
254
+ $ this ->createMock (TokenStorageInterface::class),
255
+ $ authenticationManager ,
256
+ $ this ->createMock (SessionAuthenticationStrategyInterface::class),
257
+ $ httpUtils ,
258
+ 'TheProviderKey ' ,
259
+ new DefaultAuthenticationSuccessHandler ($ httpUtils ),
260
+ $ failureHandler ,
261
+ ['require_previous_session ' => false ],
262
+ null ,
263
+ null ,
264
+ $ csrfTokenManager
265
+ );
266
+
267
+ $ listener (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MASTER_REQUEST ));
268
+ }
269
+
270
+ public function postOnlyDataProvider (): array
208
271
{
209
272
return [
210
273
[true ],
211
274
[false ],
212
275
];
213
276
}
214
277
215
- public function getUsernameForLength ()
278
+ public function getUsernameForLength (): array
216
279
{
217
280
return [
218
281
[str_repeat ('x ' , Security::MAX_USERNAME_LENGTH + 1 ), false ],
219
282
[str_repeat ('x ' , Security::MAX_USERNAME_LENGTH - 1 ), true ],
220
283
];
221
284
}
285
+
286
+ public function provideInvalidCsrfTokens (): array
287
+ {
288
+ return [
289
+ ['invalid ' ],
290
+ [['in ' => 'valid ' ]],
291
+ [null ],
292
+ ];
293
+ }
222
294
}
223
295
224
296
class DummyUserClass
0 commit comments