Skip to content

Commit

Permalink
Merge pull request #9604 from cakephp/bugfix/auth-remember
Browse files Browse the repository at this point in the history
Fix redirect to login with non GET requests and remembering location.
  • Loading branch information
markstory committed Oct 21, 2016
2 parents 932c69d + 86354fa commit 46b0ecf
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
32 changes: 27 additions & 5 deletions src/Controller/Component/AuthComponent.php
Expand Up @@ -205,7 +205,7 @@ class AuthComponent extends Component
/**
* Request object
*
* @var \Cake\Network\Request
* @var \Cake\Http\ServerRequest
*/
public $request;

Expand Down Expand Up @@ -402,14 +402,18 @@ protected function _unauthenticated(Controller $controller)
*/
protected function _loginActionRedirectUrl()
{
$currentUrl = $this->request->here(false);
$urlToRedirectBackTo = $this->_getUrlToRedirectBackTo();

$loginAction = $this->_config['loginAction'];
if ($urlToRedirectBackTo === '/') {
return $loginAction;
}

if (is_array($loginAction)) {
$loginAction['?'][static::QUERY_STRING_REDIRECT] = $currentUrl;
$loginAction['?'][static::QUERY_STRING_REDIRECT] = $urlToRedirectBackTo;
} else {
$char = strpos($loginAction, '?') === false ? '?' : '&';
$loginAction .= $char . static::QUERY_STRING_REDIRECT . '=' . urlencode($currentUrl);
$loginAction .= $char . static::QUERY_STRING_REDIRECT . '=' . urlencode($urlToRedirectBackTo);
}

return $loginAction;
Expand Down Expand Up @@ -504,7 +508,7 @@ protected function _setDefaults()
*
* @param array|\ArrayAccess|null $user The user to check the authorization of.
* If empty the user fetched from storage will be used.
* @param \Cake\Network\Request|null $request The request to authenticate for.
* @param \Cake\Http\ServerRequest|null $request The request to authenticate for.
* If empty, the current request will be used.
* @return bool True if $user is authorized, otherwise false
*/
Expand Down Expand Up @@ -992,4 +996,22 @@ public function authorizationProvider()
{
return $this->_authorizationProvider;
}

/**
* Returns the URL to redirect back to or / if not possible.
*
* This method takes the referrer into account if the
* request is not of type GET.
*
* @return string
*/
protected function _getUrlToRedirectBackTo()
{
$urlToRedirectBackTo = $this->request->here(false);
if (!$this->request->is('get')) {
$urlToRedirectBackTo = $this->request->referer(true);
}

return $urlToRedirectBackTo;
}
}
50 changes: 50 additions & 0 deletions tests/TestCase/Controller/Component/AuthComponentTest.php
Expand Up @@ -67,6 +67,8 @@ public function setUp()
});

$request = new Request();
$request->env('REQUEST_METHOD', 'GET');

$response = $this->getMockBuilder('Cake\Network\Response')
->setMethods(['stop'])
->getMock();
Expand Down Expand Up @@ -637,6 +639,53 @@ public function testLoginRedirect()
$this->assertEquals($expected, $redirectHeader);
}

/**
* testLoginRedirect method with non GET
*
* @return void
*/
public function testLoginRedirectPost()
{
$this->Auth->session->delete('Auth');

$url = '/posts/view/1';
$this->Auth->request->addParams(Router::parse($url));
$this->Auth->request->env('HTTP_REFERER', Router::url('/foo/bar', true));
$this->Auth->request->env('REQUEST_METHOD', 'POST');
$this->Auth->request->url = $this->Auth->request->here = Router::normalize($url);
$this->Auth->config('loginAction', ['controller' => 'AuthTest', 'action' => 'login']);
$event = new Event('Controller.startup', $this->Controller);
$response = $this->Auth->startup($event);

$this->assertInstanceOf('Cake\Network\Response', $response);
$expected = Router::url(['controller' => 'AuthTest', 'action' => 'login', '?' => ['redirect' => '/foo/bar']], true);
$redirectHeader = $response->header()['Location'];
$this->assertEquals($expected, $redirectHeader);
}

/**
* testLoginRedirect method with non GET and no referrer
*
* @return void
*/
public function testLoginRedirectPostNoReferer()
{
$this->Auth->session->delete('Auth');

$url = '/posts/view/1';
$this->Auth->request->addParams(Router::parse($url));
$this->Auth->request->env('REQUEST_METHOD', 'POST');
$this->Auth->request->url = $this->Auth->request->here = Router::normalize($url);
$this->Auth->config('loginAction', ['controller' => 'AuthTest', 'action' => 'login']);
$event = new Event('Controller.startup', $this->Controller);
$response = $this->Auth->startup($event);

$this->assertInstanceOf('Cake\Network\Response', $response);
$expected = Router::url(['controller' => 'AuthTest', 'action' => 'login'], true);
$redirectHeader = $response->header()['Location'];
$this->assertEquals($expected, $redirectHeader);
}

/**
* @return void
*/
Expand Down Expand Up @@ -703,6 +752,7 @@ public function testLoginRedirectDifferentBaseUrl()

$url = '/posts/add';
$this->Auth->request = $this->Controller->request = new Request($url);
$this->Auth->request->env('REQUEST_METHOD', 'GET');
$this->Auth->request->addParams(Router::parse($url));
$this->Auth->request->url = Router::normalize($url);

Expand Down

0 comments on commit 46b0ecf

Please sign in to comment.