Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite8075f0

Browse files
committed
Don't produce TypeErrors for non-string CSRF tokens
Signed-off-by: Alexander M. Turek <me@derrabus.de>
1 parent66817c2 commite8075f0

File tree

5 files changed

+106
-20
lines changed

5 files changed

+106
-20
lines changed

‎src/Symfony/Component/Security/Http/Firewall/LogoutListener.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function authenticate(RequestEvent $event)
8787
if (null !==$this->csrfTokenManager) {
8888
$csrfToken = ParameterBagUtils::getRequestParameterValue($request,$this->options['csrf_parameter']);
8989

90-
if (false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
90+
if (!\is_string($csrfToken) ||false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
9191
thrownewLogoutException('Invalid CSRF token.');
9292
}
9393
}

‎src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ protected function attemptAuthentication(Request $request)
8484
if (null !==$this->csrfTokenManager) {
8585
$csrfToken = ParameterBagUtils::getRequestParameterValue($request,$this->options['csrf_parameter']);
8686

87-
if (false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
87+
if (!\is_string($csrfToken) ||false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
8888
thrownewInvalidCsrfTokenException('Invalid CSRF token.');
8989
}
9090
}

‎src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ protected function attemptAuthentication(Request $request)
7272
if (null !==$this->csrfTokenManager) {
7373
$csrfToken = ParameterBagUtils::getRequestParameterValue($request,$this->options['csrf_parameter']);
7474

75-
if (false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
75+
if (!\is_string($csrfToken) ||false ===$this->csrfTokenManager->isTokenValid(newCsrfToken($this->options['csrf_token_id'],$csrfToken))) {
7676
thrownewInvalidCsrfTokenException('Invalid CSRF token.');
7777
}
7878
}

‎src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,28 +152,42 @@ public function testSuccessHandlerReturnsNonResponse()
152152
$listener($event);
153153
}
154154

155-
publicfunctiontestCsrfValidationFails()
155+
/**
156+
* @dataProvider provideInvalidCsrfTokens
157+
*/
158+
publicfunctiontestCsrfValidationFails($invalidToken)
156159
{
157160
$this->expectException(LogoutException::class);
158161
$tokenManager =$this->getTokenManager();
159162

160163
[$listener, ,$httpUtils,$options] =$this->getListener(null,$tokenManager);
161164

162165
$request =newRequest();
163-
$request->query->set('_csrf_token','token');
166+
if (null !==$invalidToken) {
167+
$request->query->set('_csrf_token',$invalidToken);
168+
}
164169

165170
$httpUtils->expects($this->once())
166171
->method('checkRequestPath')
167172
->with($request,$options['logout_path'])
168173
->willReturn(true);
169174

170-
$tokenManager->expects($this->once())
175+
$tokenManager
171176
->method('isTokenValid')
172177
->willReturn(false);
173178

174179
$listener(newRequestEvent($this->createMock(HttpKernelInterface::class),$request, HttpKernelInterface::MASTER_REQUEST));
175180
}
176181

182+
publicfunctionprovideInvalidCsrfTokens():array
183+
{
184+
return [
185+
['invalid'],
186+
[['in' =>'valid']],
187+
[null],
188+
];
189+
}
190+
177191
privatefunctiongetTokenManager()
178192
{
179193
return$this->createMock(CsrfTokenManagerInterface::class);

‎src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php‎

Lines changed: 86 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
useSymfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
2525
useSymfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
2626
useSymfony\Component\Security\Core\Security;
27+
useSymfony\Component\Security\Csrf\CsrfTokenManagerInterface;
2728
useSymfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
2829
useSymfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
2930
useSymfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
@@ -37,7 +38,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
3738
/**
3839
* @dataProvider getUsernameForLength
3940
*/
40-
publicfunctiontestHandleWhenUsernameLength($username,$ok)
41+
publicfunctiontestHandleWhenUsernameLength(string$username,bool$ok)
4142
{
4243
$request = Request::create('/login_check','POST', ['_username' =>$username]);
4344
$request->setSession($this->createMock(SessionInterface::class));
@@ -75,7 +76,7 @@ public function testHandleWhenUsernameLength($username, $ok)
7576
'TheProviderKey',
7677
newDefaultAuthenticationSuccessHandler($httpUtils),
7778
$failureHandler,
78-
['require_previous_session' =>false]
79+
['require_previous_session' =>false],
7980
);
8081

8182
$listener(newRequestEvent($this->createMock(HttpKernelInterface::class),$request, HttpKernelInterface::MASTER_REQUEST));
@@ -84,10 +85,8 @@ public function testHandleWhenUsernameLength($username, $ok)
8485
/**
8586
* @dataProvider postOnlyDataProvider
8687
*/
87-
publicfunctiontestHandleNonStringUsernameWithArray($postOnly)
88+
publicfunctiontestHandleNonStringUsernameWithArray(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 =newUsernamePasswordFormAuthenticationListener(
@@ -101,16 +100,18 @@ public function testHandleNonStringUsernameWithArray($postOnly)
101100
['require_previous_session' =>false,'post_only' =>$postOnly]
102101
);
103102
$event =newRequestEvent($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-
publicfunctiontestHandleNonStringUsernameWithInt($postOnly)
113+
publicfunctiontestHandleNonStringUsernameWithInt(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 =newUsernamePasswordFormAuthenticationListener(
@@ -124,16 +125,18 @@ public function testHandleNonStringUsernameWithInt($postOnly)
124125
['require_previous_session' =>false,'post_only' =>$postOnly]
125126
);
126127
$event =newRequestEvent($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-
publicfunctiontestHandleNonStringUsernameWithObject($postOnly)
138+
publicfunctiontestHandleNonStringUsernameWithObject(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 =newUsernamePasswordFormAuthenticationListener(
@@ -147,13 +150,17 @@ public function testHandleNonStringUsernameWithObject($postOnly)
147150
['require_previous_session' =>false,'post_only' =>$postOnly]
148151
);
149152
$event =newRequestEvent($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-
publicfunctiontestHandleNonStringUsernameWith__toString($postOnly)
163+
publicfunctiontestHandleNonStringUsernameWith__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-
publicfunctionpostOnlyDataProvider()
187+
/**
188+
* @dataProvider provideInvalidCsrfTokens
189+
*/
190+
publicfunctiontestInvalidCsrfToken($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(newRedirectResponse('/hello'))
208+
;
209+
210+
$failureHandler =$this->createMock(AuthenticationFailureHandlerInterface::class);
211+
$failureHandler
212+
->expects($this->once())
213+
->method('onAuthenticationFailure')
214+
->willReturn(newResponse())
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 =newUsernamePasswordFormAuthenticationListener(
227+
$this->createMock(TokenStorageInterface::class),
228+
$authenticationManager,
229+
$this->createMock(SessionAuthenticationStrategyInterface::class),
230+
$httpUtils,
231+
'TheProviderKey',
232+
newDefaultAuthenticationSuccessHandler($httpUtils),
233+
$failureHandler,
234+
['require_previous_session' =>false],
235+
null,
236+
null,
237+
$csrfTokenManager
238+
);
239+
240+
$listener(newRequestEvent($this->createMock(HttpKernelInterface::class),$request, HttpKernelInterface::MASTER_REQUEST));
241+
}
242+
243+
publicfunctionpostOnlyDataProvider():array
181244
{
182245
return [
183246
[true],
184247
[false],
185248
];
186249
}
187250

188-
publicfunctiongetUsernameForLength()
251+
publicfunctiongetUsernameForLength():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+
publicfunctionprovideInvalidCsrfTokens():array
260+
{
261+
return [
262+
['invalid'],
263+
[['in' =>'valid']],
264+
[null],
265+
];
266+
}
195267
}
196268

197269
class DummyUserClass

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp