2424use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorage ;
2525use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorageInterface ;
2626use Symfony \Component \Security \Core \Security ;
27+ use Symfony \Component \Security \Csrf \CsrfTokenManagerInterface ;
2728use Symfony \Component \Security \Http \Authentication \AuthenticationFailureHandlerInterface ;
2829use Symfony \Component \Security \Http \Authentication \DefaultAuthenticationFailureHandler ;
2930use Symfony \Component \Security \Http \Authentication \DefaultAuthenticationSuccessHandler ;
@@ -40,7 +41,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
4041 /**
4142 * @dataProvider getUsernameForLength
4243 */
43- public function testHandleWhenUsernameLength ($ username , $ ok )
44+ public function testHandleWhenUsernameLength (string $ username , bool $ ok )
4445 {
4546 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => $ username , '_password ' => 'symfony ' ]);
4647 $ request ->setSession ($ this ->createMock (SessionInterface::class));
@@ -87,10 +88,8 @@ public function testHandleWhenUsernameLength($username, $ok)
8788 /**
8889 * @dataProvider postOnlyDataProvider
8990 */
90- public function testHandleNonStringUsernameWithArray ($ postOnly )
91+ public function testHandleNonStringUsernameWithArray (bool $ postOnly )
9192 {
92- $ this ->expectException (BadRequestHttpException::class);
93- $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
9493 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => []]);
9594 $ request ->setSession ($ this ->createMock (SessionInterface::class));
9695 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -104,16 +103,18 @@ public function testHandleNonStringUsernameWithArray($postOnly)
104103 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
105104 );
106105 $ 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+
107110 $ listener ($ event );
108111 }
109112
110113 /**
111114 * @dataProvider postOnlyDataProvider
112115 */
113- public function testHandleNonStringUsernameWithInt ($ postOnly )
116+ public function testHandleNonStringUsernameWithInt (bool $ postOnly )
114117 {
115- $ this ->expectException (BadRequestHttpException::class);
116- $ this ->expectExceptionMessage ('The key "_username" must be a string, "int" given. ' );
117118 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => 42 ]);
118119 $ request ->setSession ($ this ->createMock (SessionInterface::class));
119120 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -127,16 +128,18 @@ public function testHandleNonStringUsernameWithInt($postOnly)
127128 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
128129 );
129130 $ 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+
130135 $ listener ($ event );
131136 }
132137
133138 /**
134139 * @dataProvider postOnlyDataProvider
135140 */
136- public function testHandleNonStringUsernameWithObject ($ postOnly )
141+ public function testHandleNonStringUsernameWithObject (bool $ postOnly )
137142 {
138- $ this ->expectException (BadRequestHttpException::class);
139- $ this ->expectExceptionMessage ('The key "_username" must be a string, "stdClass" given. ' );
140143 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => new \stdClass ()]);
141144 $ request ->setSession ($ this ->createMock (SessionInterface::class));
142145 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -150,13 +153,17 @@ public function testHandleNonStringUsernameWithObject($postOnly)
150153 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
151154 );
152155 $ 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+
153160 $ listener ($ event );
154161 }
155162
156163 /**
157164 * @dataProvider postOnlyDataProvider
158165 */
159- public function testHandleNonStringUsernameWith__toString ($ postOnly )
166+ public function testHandleNonStringUsernameWith__toString (bool $ postOnly )
160167 {
161168 $ usernameClass = $ this ->createMock (DummyUserClass::class);
162169 $ usernameClass
@@ -204,21 +211,86 @@ public function testHandleWhenPasswordAreNull($postOnly)
204211 $ listener ($ event );
205212 }
206213
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
208271 {
209272 return [
210273 [true ],
211274 [false ],
212275 ];
213276 }
214277
215- public function getUsernameForLength ()
278+ public function getUsernameForLength (): array
216279 {
217280 return [
218281 [str_repeat ('x ' , Security::MAX_USERNAME_LENGTH + 1 ), false ],
219282 [str_repeat ('x ' , Security::MAX_USERNAME_LENGTH - 1 ), true ],
220283 ];
221284 }
285+
286+ public function provideInvalidCsrfTokens (): array
287+ {
288+ return [
289+ ['invalid ' ],
290+ [['in ' => 'valid ' ]],
291+ [null ],
292+ ];
293+ }
222294}
223295
224296class DummyUserClass
0 commit comments