1818use Symfony \Component \HttpFoundation \Response ;
1919use Symfony \Component \HttpKernel \Event \RequestEvent ;
2020use Symfony \Component \HttpKernel \HttpKernelInterface ;
21+ use Symfony \Component \Security \Core \Authentication \Token \NullToken ;
22+ use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorage ;
2123use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorageInterface ;
22- use Symfony \Component \Security \Core \Authentication \Token \TokenInterface ;
2324use Symfony \Component \Security \Core \Exception \LogoutException ;
2425use Symfony \Component \Security \Csrf \CsrfToken ;
2526use Symfony \Component \Security \Csrf \CsrfTokenManagerInterface ;
2627use Symfony \Component \Security \Http \Event \LogoutEvent ;
2728use Symfony \Component \Security \Http \Firewall \LogoutListener ;
2829use Symfony \Component \Security \Http \HttpUtils ;
30+ use Symfony \Contracts \EventDispatcher \EventDispatcherInterface ;
2931
3032class LogoutListenerTest extends TestCase
3133{
32- public function testHandleUnmatchedPath ()
34+ private TokenStorageInterface $ tokenStorage ;
35+ private EventDispatcherInterface $ eventDispatcher ;
36+ private CsrfTokenManagerInterface $ csrfTokenManager ;
37+ private LogoutListener $ listener ;
38+
39+ protected function setUp (): void
3340 {
34- [$ listener , , $ httpUtils , $ options ] = $ this ->getListener ();
41+ $ this ->tokenStorage = new TokenStorage ();
42+ $ this ->tokenStorage ->setToken (new NullToken ());
43+ $ this ->eventDispatcher = new EventDispatcher ();
44+ $ this ->csrfTokenManager = $ this ->createMock (CsrfTokenManagerInterface::class);
45+ $ this ->listener = new LogoutListener ($ this ->tokenStorage , new HttpUtils (), $ this ->eventDispatcher , [
46+ 'csrf_parameter ' => '_csrf_token ' ,
47+ 'csrf_token_id ' => 'logout ' ,
48+ 'logout_path ' => '/logout ' ,
49+ 'target_url ' => '/ ' ,
50+ ], $ this ->csrfTokenManager );
51+ }
3552
53+ public function testHandleUnmatchedPath ()
54+ {
3655 $ request = new Request ();
3756
38- $ httpUtils ->expects ($ this ->once ())
39- ->method ('checkRequestPath ' )
40- ->with ($ request , $ options ['logout_path ' ])
41- ->willReturn (false );
42-
43- $ this ->assertFalse ($ listener ->supports ($ request ));
57+ $ this ->assertFalse ($ this ->listener ->supports ($ request ));
4458 }
4559
4660 public function testHandleMatchedPathWithCsrfValidation ()
4761 {
48- $ tokenManager = $ this ->getTokenManager ();
49- $ dispatcher = $ this ->getEventDispatcher ();
50-
51- [$ listener , $ tokenStorage , $ httpUtils , $ options ] = $ this ->getListener ($ dispatcher , $ tokenManager );
62+ $ request = Request::create ('/logout?_csrf_token=token ' );
5263
53- $ request = new Request ();
54- $ request ->query ->set ('_csrf_token ' , 'token ' );
55-
56- $ httpUtils ->expects ($ this ->once ())
57- ->method ('checkRequestPath ' )
58- ->with ($ request , $ options ['logout_path ' ])
59- ->willReturn (true );
60-
61- $ tokenManager ->expects ($ this ->once ())
64+ $ this ->csrfTokenManager ->expects ($ this ->once ())
6265 ->method ('isTokenValid ' )
6366 ->willReturn (true );
6467
6568 $ response = new Response ();
66- $ dispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
69+ $ this -> eventDispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
6770 $ event ->setResponse ($ response );
6871 });
6972
70- $ tokenStorage ->expects ($ this ->once ())
71- ->method ('getToken ' )
72- ->willReturn ($ this ->getToken ());
73-
74- $ tokenStorage ->expects ($ this ->once ())
75- ->method ('setToken ' )
76- ->with (null );
77-
7873 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
7974
80- $ this ->assertTrue ($ listener ->supports ($ request ));
81- $ listener ->authenticate ($ event );
75+ $ this ->assertTrue ($ this -> listener ->supports ($ request ));
76+ $ this -> listener ->authenticate ($ event );
8277
8378 $ this ->assertSame ($ response , $ event ->getResponse ());
79+ $ this ->assertNull ($ this ->tokenStorage ->getToken ());
8480 }
8581
8682 public function testHandleMatchedPathWithCsrfInQueryParamAndBody ()
8783 {
88- $ tokenManager = $ this ->getTokenManager ();
89- $ dispatcher = $ this ->getEventDispatcher ();
90-
91- [$ listener , $ tokenStorage , $ httpUtils , $ options ] = $ this ->getListener ($ dispatcher , $ tokenManager );
92-
93- $ request = new Request ();
94- $ request ->query ->set ('_csrf_token ' , 'token ' );
95- $ request ->request ->set ('_csrf_token ' , 'token2 ' );
84+ $ request = Request::create ('/logout?_csrf_token=token ' , 'GET ' , ['_csrf_token ' => 'token2 ' ]);
9685
97- $ httpUtils ->expects ($ this ->once ())
98- ->method ('checkRequestPath ' )
99- ->with ($ request , $ options ['logout_path ' ])
100- ->willReturn (true );
101-
102- $ tokenManager ->expects ($ this ->once ())
86+ $ this ->csrfTokenManager ->expects ($ this ->once ())
10387 ->method ('isTokenValid ' )
10488 ->with ($ this ->callback (function ($ token ) {
10589 return $ token instanceof CsrfToken && 'token2 ' === $ token ->getValue ();
10690 }))
10791 ->willReturn (true );
10892
10993 $ response = new Response ();
110- $ dispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
94+ $ this -> eventDispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
11195 $ event ->setResponse ($ response );
11296 });
11397
114- $ tokenStorage ->expects ($ this ->once ())
115- ->method ('getToken ' )
116- ->willReturn ($ token = $ this ->getToken ());
117-
118- $ tokenStorage ->expects ($ this ->once ())
119- ->method ('setToken ' )
120- ->with (null );
121-
12298 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
12399
124- $ this ->assertTrue ($ listener ->supports ($ request ));
125- $ listener ->authenticate ($ event );
100+ $ this ->assertTrue ($ this -> listener ->supports ($ request ));
101+ $ this -> listener ->authenticate ($ event );
126102
127103 $ this ->assertSame ($ response , $ event ->getResponse ());
104+ $ this ->assertNull ($ this ->tokenStorage ->getToken ());
128105 }
129106
130107 public function testHandleMatchedPathWithoutCsrfValidation ()
131108 {
132- $ dispatcher = $ this ->getEventDispatcher ();
133- [$ listener , $ tokenStorage , $ httpUtils , $ options ] = $ this ->getListener ($ dispatcher );
109+ $ listener = new LogoutListener ($ this ->tokenStorage , new HttpUtils (), $ this ->eventDispatcher , [
110+ 'csrf_parameter ' => '_csrf_token ' ,
111+ 'csrf_token_id ' => 'logout ' ,
112+ 'logout_path ' => '/logout ' ,
113+ 'target_url ' => '/ ' ,
114+ ]);
134115
135- $ request = new Request ();
136-
137- $ httpUtils ->expects ($ this ->once ())
138- ->method ('checkRequestPath ' )
139- ->with ($ request , $ options ['logout_path ' ])
140- ->willReturn (true );
116+ $ request = Request::create ('/logout ' );
141117
142118 $ response = new Response ();
143- $ dispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
119+ $ this -> eventDispatcher ->addListener (LogoutEvent::class, function (LogoutEvent $ event ) use ($ response ) {
144120 $ event ->setResponse ($ response );
145121 });
146122
147- $ tokenStorage ->expects ($ this ->once ())
148- ->method ('getToken ' )
149- ->willReturn ($ this ->getToken ());
150-
151- $ tokenStorage ->expects ($ this ->once ())
152- ->method ('setToken ' )
153- ->with (null );
154-
155123 $ event = new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST );
156124
157125 $ this ->assertTrue ($ listener ->supports ($ request ));
158126 $ listener ->authenticate ($ event );
159127
160128 $ this ->assertSame ($ response , $ event ->getResponse ());
129+ $ this ->assertNull ($ this ->tokenStorage ->getToken ());
161130 }
162131
163132 public function testNoResponseSet ()
164133 {
165- [$ listener , , $ httpUtils , $ options ] = $ this ->getListener ();
166-
167- $ request = new Request ();
168-
169- $ httpUtils ->expects ($ this ->once ())
170- ->method ('checkRequestPath ' )
171- ->with ($ request , $ options ['logout_path ' ])
172- ->willReturn (true );
134+ $ request = Request::create ('/logout ' );
173135
174136 $ this ->expectException (\RuntimeException::class);
175137
176- $ this ->assertTrue ($ listener ->supports ($ request ));
177- $ listener ->authenticate (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST ));
138+ $ this ->assertTrue ($ this -> listener ->supports ($ request ));
139+ $ this -> listener ->authenticate (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST ));
178140 }
179141
180142 #[DataProvider('provideInvalidCsrfTokens ' )]
181143 public function testCsrfValidationFails ($ invalidToken )
182144 {
183- $ tokenManager = $ this ->getTokenManager ();
184-
185- [$ listener , , $ httpUtils , $ options ] = $ this ->getListener (null , $ tokenManager );
186-
187- $ request = new Request ();
145+ $ request = Request::create ('/logout ' );
188146 if (null !== $ invalidToken ) {
189147 $ request ->query ->set ('_csrf_token ' , $ invalidToken );
190148 }
191149
192- $ httpUtils ->expects ($ this ->once ())
193- ->method ('checkRequestPath ' )
194- ->with ($ request , $ options ['logout_path ' ])
195- ->willReturn (true );
196-
197- $ tokenManager
150+ $ this ->csrfTokenManager
198151 ->method ('isTokenValid ' )
199152 ->willReturn (false );
200153
201154 $ this ->expectException (LogoutException::class);
202155
203- $ this ->assertTrue ($ listener ->supports ($ request ));
204- $ listener ->authenticate (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST ));
156+ $ this ->assertTrue ($ this -> listener ->supports ($ request ));
157+ $ this -> listener ->authenticate (new RequestEvent ($ this ->createMock (HttpKernelInterface::class), $ request , HttpKernelInterface::MAIN_REQUEST ));
205158 }
206159
207160 public static function provideInvalidCsrfTokens (): array
@@ -212,47 +165,4 @@ public static function provideInvalidCsrfTokens(): array
212165 [null ],
213166 ];
214167 }
215-
216- private function getTokenManager ()
217- {
218- return $ this ->createMock (CsrfTokenManagerInterface::class);
219- }
220-
221- private function getTokenStorage ()
222- {
223- return $ this ->createMock (TokenStorageInterface::class);
224- }
225-
226- private function getHttpUtils ()
227- {
228- return $ this ->createMock (HttpUtils::class);
229- }
230-
231- private function getListener ($ eventDispatcher = null , $ tokenManager = null ): array
232- {
233- $ listener = new LogoutListener (
234- $ tokenStorage = $ this ->getTokenStorage (),
235- $ httpUtils = $ this ->getHttpUtils (),
236- $ eventDispatcher ?? $ this ->getEventDispatcher (),
237- $ options = [
238- 'csrf_parameter ' => '_csrf_token ' ,
239- 'csrf_token_id ' => 'logout ' ,
240- 'logout_path ' => '/logout ' ,
241- 'target_url ' => '/ ' ,
242- ],
243- $ tokenManager
244- );
245-
246- return [$ listener , $ tokenStorage , $ httpUtils , $ options ];
247- }
248-
249- private function getEventDispatcher ()
250- {
251- return new EventDispatcher ();
252- }
253-
254- private function getToken ()
255- {
256- return $ this ->createMock (TokenInterface::class);
257- }
258168}
0 commit comments