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 ;
@@ -37,7 +38,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
37
38
/**
38
39
* @dataProvider getUsernameForLength
39
40
*/
40
- public function testHandleWhenUsernameLength ($ username , $ ok )
41
+ public function testHandleWhenUsernameLength (string $ username , bool $ ok )
41
42
{
42
43
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => $ username ]);
43
44
$ request ->setSession ($ this ->createMock (SessionInterface::class));
@@ -84,10 +85,8 @@ public function testHandleWhenUsernameLength($username, $ok)
84
85
/**
85
86
* @dataProvider postOnlyDataProvider
86
87
*/
87
- public function testHandleNonStringUsernameWithArray ($ postOnly )
88
+ public function testHandleNonStringUsernameWithArray (bool $ postOnly )
88
89
{
89
- $ this ->expectException (BadRequestHttpException::class);
90
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "array" given. ' );
91
90
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => []]);
92
91
$ request ->setSession ($ this ->createMock (SessionInterface::class));
93
92
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -101,16 +100,18 @@ public function testHandleNonStringUsernameWithArray($postOnly)
101
100
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
102
101
);
103
102
$ 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
+
104
107
$ listener ($ event );
105
108
}
106
109
107
110
/**
108
111
* @dataProvider postOnlyDataProvider
109
112
*/
110
- public function testHandleNonStringUsernameWithInt ($ postOnly )
113
+ public function testHandleNonStringUsernameWithInt (bool $ postOnly )
111
114
{
112
- $ this ->expectException (BadRequestHttpException::class);
113
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "integer" given. ' );
114
115
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => 42 ]);
115
116
$ request ->setSession ($ this ->createMock (SessionInterface::class));
116
117
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -124,16 +125,18 @@ public function testHandleNonStringUsernameWithInt($postOnly)
124
125
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
125
126
);
126
127
$ 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
+
127
132
$ listener ($ event );
128
133
}
129
134
130
135
/**
131
136
* @dataProvider postOnlyDataProvider
132
137
*/
133
- public function testHandleNonStringUsernameWithObject ($ postOnly )
138
+ public function testHandleNonStringUsernameWithObject (bool $ postOnly )
134
139
{
135
- $ this ->expectException (BadRequestHttpException::class);
136
- $ this ->expectExceptionMessage ('The key "_username" must be a string, "object" given. ' );
137
140
$ request = Request::create ('/login_check ' , 'POST ' , ['_username ' => new \stdClass ()]);
138
141
$ request ->setSession ($ this ->createMock (SessionInterface::class));
139
142
$ listener = new UsernamePasswordFormAuthenticationListener (
@@ -147,13 +150,17 @@ public function testHandleNonStringUsernameWithObject($postOnly)
147
150
['require_previous_session ' => false , 'post_only ' => $ postOnly ]
148
151
);
149
152
$ 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
+
150
157
$ listener ($ event );
151
158
}
152
159
153
160
/**
154
161
* @dataProvider postOnlyDataProvider
155
162
*/
156
- public function testHandleNonStringUsernameWith__toString ($ postOnly )
163
+ public function testHandleNonStringUsernameWith__toString (bool $ postOnly )
157
164
{
158
165
$ usernameClass = $ this ->createMock (DummyUserClass::class);
159
166
$ usernameClass
@@ -177,21 +184,86 @@ public function testHandleNonStringUsernameWith__toString($postOnly)
177
184
$ listener ($ event );
178
185
}
179
186
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
181
244
{
182
245
return [
183
246
[true ],
184
247
[false ],
185
248
];
186
249
}
187
250
188
- public function getUsernameForLength ()
251
+ public function getUsernameForLength (): array
189
252
{
190
253
return [
191
254
[str_repeat ('x ' , Security::MAX_USERNAME_LENGTH + 1 ), false ],
192
255
[str_repeat ('x ' , Security::MAX_USERNAME_LENGTH - 1 ), true ],
193
256
];
194
257
}
258
+
259
+ public function provideInvalidCsrfTokens (): array
260
+ {
261
+ return [
262
+ ['invalid ' ],
263
+ [['in ' => 'valid ' ]],
264
+ [null ],
265
+ ];
266
+ }
195
267
}
196
268
197
269
class DummyUserClass
0 commit comments