14
14
use Symfony \Bundle \SecurityBundle \Security \FirewallConfig ;
15
15
use Symfony \Bundle \SecurityBundle \Security \Security ;
16
16
use Symfony \Bundle \SecurityBundle \Tests \Functional \Bundle \SecuredPageBundle \Security \Core \User \ArrayUserProvider ;
17
+ use Symfony \Component \EventDispatcher \EventDispatcherInterface ;
17
18
use Symfony \Component \HttpFoundation \JsonResponse ;
18
19
use Symfony \Component \HttpFoundation \Request ;
20
+ use Symfony \Component \HttpFoundation \Response ;
21
+ use Symfony \Component \HttpKernel \Event \RequestEvent ;
22
+ use Symfony \Component \HttpKernel \KernelEvents ;
19
23
use Symfony \Component \Security \Core \Authentication \Token \UsernamePasswordToken ;
20
24
use Symfony \Component \Security \Core \User \InMemoryUser ;
21
25
use Symfony \Component \Security \Core \User \PasswordAuthenticatedUserInterface ;
22
26
use Symfony \Component \Security \Core \User \UserInterface ;
23
- use Symfony \Component \Security \Csrf \CsrfTokenManagerInterface ;
24
27
25
28
class SecurityTest extends AbstractWebTestCase
26
29
{
@@ -38,8 +41,10 @@ public function testServiceIsFunctional()
38
41
$ security = $ container ->get ('functional_test.security.helper ' );
39
42
$ this ->assertTrue ($ security ->isGranted ('ROLE_USER ' ));
40
43
$ this ->assertSame ($ token , $ security ->getToken ());
41
- $ this ->assertInstanceOf (FirewallConfig::class, $ firewallConfig = $ security ->getFirewallConfig (new Request ()));
42
- $ this ->assertSame ('default ' , $ firewallConfig ->getName ());
44
+ $ request = new Request ();
45
+ $ request ->server ->set ('REQUEST_URI ' , '/main/foo ' );
46
+ $ this ->assertInstanceOf (FirewallConfig::class, $ firewallConfig = $ security ->getFirewallConfig ($ request ));
47
+ $ this ->assertSame ('main ' , $ firewallConfig ->getName ());
43
48
}
44
49
45
50
/**
@@ -86,14 +91,14 @@ public function userWillBeMarkedAsChangedIfRolesHasChangedProvider()
86
91
}
87
92
88
93
/**
89
- * @testWith ["json_login "]
94
+ * @testWith ["form_login "]
90
95
* ["Symfony\\Bundle\\SecurityBundle\\Tests\\Functional\\Bundle\\AuthenticatorBundle\\ApiAuthenticator"]
91
96
*/
92
97
public function testLogin (string $ authenticator )
93
98
{
94
- $ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config.yml ' ]);
95
- static ::getContainer ()->get (WelcomeController ::class)->authenticator = $ authenticator ;
96
- $ client ->request ('GET ' , '/welcome ' );
99
+ $ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config.yml ' , ' debug ' > true ]);
100
+ static ::getContainer ()->get (ForceLoginController ::class)->authenticator = $ authenticator ;
101
+ $ client ->request ('GET ' , '/main/force-login ' );
97
102
$ response = $ client ->getResponse ();
98
103
99
104
$ this ->assertInstanceOf (JsonResponse::class, $ response );
@@ -104,8 +109,10 @@ public function testLogin(string $authenticator)
104
109
105
110
public function testLogout ()
106
111
{
107
- $ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config.yml ' ]);
108
- $ client ->request ('GET ' , '/force-logout ' );
112
+ $ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config.yml ' , 'debug ' => true ]);
113
+ $ client ->loginUser (new InMemoryUser ('chalasr ' , 'the-password ' , ['ROLE_FOO ' ]), 'main ' );
114
+
115
+ $ client ->request ('GET ' , '/main/force-logout ' );
109
116
$ response = $ client ->getResponse ();
110
117
111
118
$ this ->assertSame (200 , $ response ->getStatusCode ());
@@ -114,9 +121,39 @@ public function testLogout()
114
121
}
115
122
116
123
public function testLogoutWithCsrf ()
124
+ {
125
+ $ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config_logout_csrf.yml ' , 'debug ' => true ]);
126
+ $ client ->loginUser (new InMemoryUser ('chalasr ' , 'the-password ' , ['ROLE_FOO ' ]), 'main ' );
127
+
128
+ // put a csrf token in the storage
129
+ /** @var EventDispatcherInterface $eventDispatcher */
130
+ $ eventDispatcher = static ::getContainer ()->get (EventDispatcherInterface::class);
131
+ $ setCsrfToken = function (RequestEvent $ event ) {
132
+ static ::getContainer ()->get ('security.csrf.token_storage ' )->setToken ('logout ' , 'bar ' );
133
+ $ event ->setResponse (new Response ('' ));
134
+ };
135
+ $ eventDispatcher ->addListener (KernelEvents::REQUEST , $ setCsrfToken );
136
+ try {
137
+ $ client ->request ('GET ' , '/ ' .uniqid ('' , true ));
138
+ } finally {
139
+ $ eventDispatcher ->removeListener (KernelEvents::REQUEST , $ setCsrfToken );
140
+ }
141
+
142
+ static ::getContainer ()->get (LogoutController::class)->checkCsrf = true ;
143
+ $ client ->request ('GET ' , '/main/force-logout ' , ['_csrf_token ' => 'bar ' ]);
144
+ $ response = $ client ->getResponse ();
145
+
146
+ $ this ->assertSame (200 , $ response ->getStatusCode ());
147
+ $ this ->assertNull (static ::getContainer ()->get ('security.helper ' )->getUser ());
148
+ $ this ->assertSame (['message ' => 'Logout successful ' ], json_decode ($ response ->getContent (), true ));
149
+ }
150
+
151
+ public function testLogoutBypassCsrf ()
117
152
{
118
153
$ client = $ this ->createClient (['test_case ' => 'SecurityHelper ' , 'root_config ' => 'config_logout_csrf.yml ' ]);
119
- $ client ->request ('GET ' , '/force-logout ' );
154
+ $ client ->loginUser (new InMemoryUser ('chalasr ' , 'the-password ' , ['ROLE_FOO ' ]), 'main ' );
155
+
156
+ $ client ->request ('GET ' , '/main/force-logout ' );
120
157
$ response = $ client ->getResponse ();
121
158
122
159
$ this ->assertSame (200 , $ response ->getStatusCode ());
@@ -232,17 +269,17 @@ public function eraseCredentials(): void
232
269
}
233
270
}
234
271
235
- class WelcomeController
272
+ class ForceLoginController
236
273
{
237
- public $ authenticator = 'json_login ' ;
274
+ public $ authenticator = 'form_login ' ;
238
275
239
276
public function __construct (private Security $ security )
240
277
{
241
278
}
242
279
243
280
public function welcome ()
244
281
{
245
- $ user = new InMemoryUser ('chalasr ' , '' , ['ROLE_USER ' ]);
282
+ $ user = new InMemoryUser ('chalasr ' , 'the-password ' , ['ROLE_FOO ' ]);
246
283
$ this ->security ->login ($ user , $ this ->authenticator );
247
284
248
285
return new JsonResponse (['message ' => sprintf ('Welcome @%s! ' , $ this ->security ->getUser ()->getUserIdentifier ())]);
@@ -251,18 +288,24 @@ public function welcome()
251
288
252
289
class LogoutController
253
290
{
254
- public function __construct (private Security $ security , private ?CsrfTokenManagerInterface $ csrfTokenManager = null )
291
+ public $ checkCsrf = false ;
292
+
293
+ public function __construct (private Security $ security )
255
294
{
256
295
}
257
296
258
- public function logout (Request $ request )
297
+ public function logout (UserInterface $ user )
259
298
{
260
- $ this ->security ->login (new InMemoryUser ('chalasr ' , '' , ['ROLE_USER ' ]), 'json_login ' , 'default ' );
261
- if ($ this ->csrfTokenManager ) {
262
- $ request ->query ->set ('_csrf_token ' , (string ) $ this ->csrfTokenManager ->getToken ('logout ' ));
263
- }
264
- $ this ->security ->logout ();
299
+ $ this ->security ->logout ($ this ->checkCsrf );
265
300
266
301
return new JsonResponse (['message ' => 'Logout successful ' ]);
267
302
}
268
303
}
304
+
305
+ class LoggedInController
306
+ {
307
+ public function __invoke (UserInterface $ user )
308
+ {
309
+ return new JsonResponse (['message ' => sprintf ('Welcome back @%s ' , $ user ->getUserIdentifier ())]);
310
+ }
311
+ }
0 commit comments