diff --git a/src/Controller/Component/AuthComponent.php b/src/Controller/Component/AuthComponent.php index 1495bdc5dfc..e8b5a2220d2 100644 --- a/src/Controller/Component/AuthComponent.php +++ b/src/Controller/Component/AuthComponent.php @@ -406,7 +406,8 @@ protected function _loginActionRedirectUrl() if (is_array($loginAction)) { $loginAction['?'][static::QUERY_STRING_REDIRECT] = $currentUrl; } else { - $loginAction .= '?' . static::QUERY_STRING_REDIRECT . '=' . rawurlencode($currentUrl); + $char = strpos($loginAction, '?') === false ? '?' : '&'; + $loginAction .= $char . static::QUERY_STRING_REDIRECT . '=' . urlencode($currentUrl); } return $loginAction; diff --git a/tests/TestCase/Controller/Component/AuthComponentTest.php b/tests/TestCase/Controller/Component/AuthComponentTest.php index a226496f94e..38cc4c19ba6 100644 --- a/tests/TestCase/Controller/Component/AuthComponentTest.php +++ b/tests/TestCase/Controller/Component/AuthComponentTest.php @@ -661,6 +661,30 @@ public function testLoginRedirectQueryString() $this->assertEquals($expected, $redirectHeader); } + /** + * @return void + */ + public function testLoginRedirectQueryStringWithComplexLoginActionUrl() + { + $this->Auth->session->delete('Auth'); + $url = '/posts/view/29'; + $this->Auth->request->addParams(Router::parse($url)); + $this->Auth->request->url = $this->Auth->request->here = Router::normalize($url); + $this->Auth->request->query = [ + 'print' => 'true', + 'refer' => 'menu' + ]; + + $this->Auth->session->delete('Auth'); + $this->Auth->config('loginAction', '/auth_test/login/passed-param?a=b'); + $event = new Event('Controller.startup', $this->Controller); + $response = $this->Auth->startup($event); + + $redirectHeader = $response->header()['Location']; + $expected = Router::url(['controller' => 'AuthTest', 'action' => 'login', 'passed-param', '?' => ['a' => 'b', 'redirect' => '/posts/view/29?print=true&refer=menu']], true); + $this->assertEquals($expected, $redirectHeader); + } + /** * @return void */ @@ -1483,7 +1507,7 @@ public function testStatelessAuthNoRedirect() * @return void * @triggers Controller.startup $this->Controller */ - public function testStatelessFollowedByStatefulAuth() + public function testStatelessAuthRedirectToLogin() { $this->Auth->response = $this->getMockBuilder('Cake\Network\Response') ->setMethods(['stop', 'statusCode', 'send'])