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 ;
@@ -37,7 +38,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
3738 /**
3839 * @dataProvider getUsernameForLength
3940 */
40- public function testHandleWhenUsernameLength ($ username , $ ok )
41+ public function testHandleWhenUsernameLength (string $ username , bool $ ok )
4142 {
4243 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => $ username ]);
4344 $ request ->setSession ($ this ->createMock (SessionInterface::class));
@@ -84,10 +85,8 @@ public function testHandleWhenUsernameLength($username, $ok)
8485 /**
8586 * @dataProvider postOnlyDataProvider
8687 */
87- public function testHandleNonStringUsernameWithArray ($ postOnly )
88+ public function testHandleNonStringUsernameWithArray (bool $ postOnly )
8889 {
89- $ this ->expectException (BadRequestHttpException::class);
90- $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
9190 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => []]);
9291 $ request ->setSession ($ this ->createMock (SessionInterface::class));
9392 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -101,16 +100,18 @@ public function testHandleNonStringUsernameWithArray($postOnly)
101100 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
102101 );
103102 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MASTER_REQUEST );
103+
104+ $ this ->expectException (BadRequestHttpException::class);
105+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
106+
104107 $ listener ($ event );
105108 }
106109
107110 /**
108111 * @dataProvider postOnlyDataProvider
109112 */
110- public function testHandleNonStringUsernameWithInt ($ postOnly )
113+ public function testHandleNonStringUsernameWithInt (bool $ postOnly )
111114 {
112- $ this ->expectException (BadRequestHttpException::class);
113- $ this ->expectExceptionMessage ('The key "_username" must be a string, "integer" given. ' );
114115 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => 42 ]);
115116 $ request ->setSession ($ this ->createMock (SessionInterface::class));
116117 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -124,16 +125,18 @@ public function testHandleNonStringUsernameWithInt($postOnly)
124125 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
125126 );
126127 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MASTER_REQUEST );
128+
129+ $ this ->expectException (BadRequestHttpException::class);
130+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "integer" given. ' );
131+
127132 $ listener ($ event );
128133 }
129134
130135 /**
131136 * @dataProvider postOnlyDataProvider
132137 */
133- public function testHandleNonStringUsernameWithObject ($ postOnly )
138+ public function testHandleNonStringUsernameWithObject (bool $ postOnly )
134139 {
135- $ this ->expectException (BadRequestHttpException::class);
136- $ this ->expectExceptionMessage ('The key "_username" must be a string, "object" given. ' );
137140 $ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => new \stdClass ()]);
138141 $ request ->setSession ($ this ->createMock (SessionInterface::class));
139142 $ listener = new UsernamePasswordFormAuthenticationListener (
@@ -147,13 +150,17 @@ public function testHandleNonStringUsernameWithObject($postOnly)
147150 ['require_previous_session ' => false , 'post_only ' => $ postOnly ]
148151 );
149152 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MASTER_REQUEST );
153+
154+ $ this ->expectException (BadRequestHttpException::class);
155+ $ this ->expectExceptionMessage ('The key "_username" must be a string, "object" given. ' );
156+
150157 $ listener ($ event );
151158 }
152159
153160 /**
154161 * @dataProvider postOnlyDataProvider
155162 */
156- public function testHandleNonStringUsernameWith__toString ($ postOnly )
163+ public function testHandleNonStringUsernameWith__toString (bool $ postOnly )
157164 {
158165 $ usernameClass = $ this ->createMock (DummyUserClass::class);
159166 $ usernameClass
@@ -177,21 +184,86 @@ public function testHandleNonStringUsernameWith__toString($postOnly)
177184 $ listener ($ event );
178185 }
179186
180- public function postOnlyDataProvider ()
187+ /**
188+ * @dataProvider provideInvalidCsrfTokens
189+ */
190+ public function testInvalidCsrfToken ($ invalidToken )
191+ {
192+ $ formBody = ['_username ' => 'fabien ' , '_password ' => 'symfony ' ];
193+ if (null !== $ invalidToken ) {
194+ $ formBody ['_csrf_token ' ] = $ invalidToken ;
195+ }
196+
197+ $ request = Request::create ('/login_check ' , 'POST ' , $ formBody );
198+ $ request ->setSession ($ this ->createMock (SessionInterface::class));
199+
200+ $ httpUtils = $ this ->createMock (HttpUtils::class);
201+ $ httpUtils
202+ ->method ('checkRequestPath ' )
203+ ->willReturn (true )
204+ ;
205+ $ httpUtils
206+ ->method ('createRedirectResponse ' )
207+ ->willReturn (new RedirectResponse ('/hello ' ))
208+ ;
209+
210+ $ failureHandler = $ this ->createMock (AuthenticationFailureHandlerInterface::class);
211+ $ failureHandler
212+ ->expects ($ this ->once ())
213+ ->method ('onAuthenticationFailure ' )
214+ ->willReturn (new Response ())
215+ ;
216+
217+ $ authenticationManager = $ this ->createMock (AuthenticationProviderManager::class);
218+ $ authenticationManager
219+ ->expects ($ this ->never ())
220+ ->method ('authenticate ' )
221+ ;
222+
223+ $ csrfTokenManager = $ this ->createMock (CsrfTokenManagerInterface::class);
224+ $ csrfTokenManager ->method ('isTokenValid ' )->willReturn (false );
225+
226+ $ listener = new UsernamePasswordFormAuthenticationListener (
227+ $ this ->createMock (TokenStorageInterface::class),
228+ $ authenticationManager ,
229+ $ this ->createMock (SessionAuthenticationStrategyInterface::class),
230+ $ httpUtils ,
231+ 'TheProviderKey ' ,
232+ new DefaultAuthenticationSuccessHandler ($ httpUtils ),
233+ $ failureHandler ,
234+ ['require_previous_session ' => false ],
235+ null ,
236+ null ,
237+ $ csrfTokenManager
238+ );
239+
240+ $ listener (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MASTER_REQUEST ));
241+ }
242+
243+ public function postOnlyDataProvider (): array
181244 {
182245 return [
183246 [true ],
184247 [false ],
185248 ];
186249 }
187250
188- public function getUsernameForLength ()
251+ public function getUsernameForLength (): array
189252 {
190253 return [
191254 [str_repeat ('x ' , Security::MAX_USERNAME_LENGTH + 1 ), false ],
192255 [str_repeat ('x ' , Security::MAX_USERNAME_LENGTH - 1 ), true ],
193256 ];
194257 }
258+
259+ public function provideInvalidCsrfTokens (): array
260+ {
261+ return [
262+ ['invalid ' ],
263+ [['in ' => 'valid ' ]],
264+ [null ],
265+ ];
266+ }
195267}
196268
197269class DummyUserClass
0 commit comments