99
1010namespace Flarum \Forum \Controller ;
1111
12+ use Flarum \Foundation \Config ;
1213use Flarum \Http \Exception \TokenMismatchException ;
1314use Flarum \Http \Rememberer ;
1415use Flarum \Http \RequestUtil ;
2021use Illuminate \Support \Arr ;
2122use Laminas \Diactoros \Response \HtmlResponse ;
2223use Laminas \Diactoros \Response \RedirectResponse ;
24+ use Laminas \Diactoros \Uri ;
2325use Psr \Http \Message \ResponseInterface ;
2426use Psr \Http \Message \ServerRequestInterface as Request ;
2527use Psr \Http \Server \RequestHandlerInterface ;
@@ -51,25 +53,33 @@ class LogOutController implements RequestHandlerInterface
5153 */
5254 protected $ url ;
5355
56+ /**
57+ * @var Config
58+ */
59+ protected $ config ;
60+
5461 /**
5562 * @param Dispatcher $events
5663 * @param SessionAuthenticator $authenticator
5764 * @param Rememberer $rememberer
5865 * @param Factory $view
5966 * @param UrlGenerator $url
67+ * @param Config $config
6068 */
6169 public function __construct (
6270 Dispatcher $ events ,
6371 SessionAuthenticator $ authenticator ,
6472 Rememberer $ rememberer ,
6573 Factory $ view ,
66- UrlGenerator $ url
74+ UrlGenerator $ url ,
75+ Config $ config
6776 ) {
6877 $ this ->events = $ events ;
6978 $ this ->authenticator = $ authenticator ;
7079 $ this ->rememberer = $ rememberer ;
7180 $ this ->view = $ view ;
7281 $ this ->url = $ url ;
82+ $ this ->config = $ config ;
7383 }
7484
7585 /**
@@ -81,29 +91,29 @@ public function handle(Request $request): ResponseInterface
8191 {
8292 $ session = $ request ->getAttribute ('session ' );
8393 $ actor = RequestUtil::getActor ($ request );
94+ $ base = $ this ->url ->to ('forum ' )->base ();
8495
85- $ url = Arr::get ($ request ->getQueryParams (), 'return ' , $ this ->url ->to ('forum ' )->base ());
96+ $ returnUrl = Arr::get ($ request ->getQueryParams (), 'return ' );
97+ $ return = $ this ->sanitizeReturnUrl ((string ) $ returnUrl , $ base );
8698
87- // If there is no user logged in, return to the index.
99+ // If there is no user logged in, return to the index or the return url if it's set .
88100 if ($ actor ->isGuest ()) {
89- return new RedirectResponse ($ url );
101+ return new RedirectResponse ($ return );
90102 }
91103
92104 // If a valid CSRF token hasn't been provided, show a view which will
93105 // allow the user to press a button to complete the log out process.
94106 $ csrfToken = $ session ->token ();
95107
96108 if (Arr::get ($ request ->getQueryParams (), 'token ' ) !== $ csrfToken ) {
97- $ return = Arr::get ($ request ->getQueryParams (), 'return ' );
98-
99109 $ view = $ this ->view ->make ('flarum.forum::log-out ' )
100- ->with ('url ' , $ this ->url ->to ('forum ' )->route ('logout ' ). '?token= ' . $ csrfToken.( $ return ? '&return= ' . urlencode ($ return ) : '' ));
110+ ->with ('url ' , $ this ->url ->to ('forum ' )->route ('logout ' ) . '?token= ' . $ csrfToken . ( $ returnUrl ? '&return= ' . urlencode ($ return ) : '' ));
101111
102112 return new HtmlResponse ($ view ->render ());
103113 }
104114
105115 $ accessToken = $ session ->get ('access_token ' );
106- $ response = new RedirectResponse ($ url );
116+ $ response = new RedirectResponse ($ return );
107117
108118 $ this ->authenticator ->logOut ($ session );
109119
@@ -113,4 +123,33 @@ public function handle(Request $request): ResponseInterface
113123
114124 return $ this ->rememberer ->forget ($ response );
115125 }
126+
127+ protected function sanitizeReturnUrl (string $ url , string $ base ): Uri
128+ {
129+ if (empty ($ url )) {
130+ return new Uri ($ base );
131+ }
132+
133+ try {
134+ $ parsedUrl = new Uri ($ url );
135+ } catch (\InvalidArgumentException $ e ) {
136+ return new Uri ($ base );
137+ }
138+
139+ if (in_array ($ parsedUrl ->getHost (), $ this ->getAllowedRedirectDomains ())) {
140+ return $ parsedUrl ;
141+ }
142+
143+ return new Uri ($ base );
144+ }
145+
146+ protected function getAllowedRedirectDomains (): array
147+ {
148+ $ forumUri = $ this ->config ->url ();
149+
150+ return array_merge (
151+ [$ forumUri ->getHost ()],
152+ $ this ->config ->offsetGet ('redirectDomains ' ) ?? []
153+ );
154+ }
116155}
0 commit comments