Skip to content

Commit

Permalink
Also store the CSRF token in request->params for easier access.
Browse files Browse the repository at this point in the history
Because the name of the cookie and field are configurable having
a constant place for the token will be useful.
  • Loading branch information
markstory committed Nov 8, 2013
1 parent c92ae61 commit fc6b93d
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
20 changes: 16 additions & 4 deletions Cake/Controller/Component/CsrfComponent.php
Expand Up @@ -59,8 +59,10 @@ class CsrfComponent extends Component {
* Startup callback.
*
* Validates the CSRF token for POST data. If
* the request is a GET request, and the cookie value
* is absent a cookie will be set.
* the request is a GET request, and the cookie value is absent a cookie will be set.
*
* Once a cookie is set it will be copied into request->params['_csrfToken']
* so that application and framework code can easily access the csrf token.
*
* RequestAction requests do not get checked, nor will
* they set a cookie should it be missing.
Expand All @@ -74,11 +76,16 @@ public function startup(Event $event) {
$response = $controller->response;
$cookieName = $this->settings['cookieName'];

$cookieData = $request->cookie($cookieName);
if ($cookieData) {
$request->params['_csrfToken'] = $cookieData;
}

if ($request->is('requested')) {
return;
}

if ($request->is('get') && $request->cookie($cookieName) === null) {
if ($request->is('get') && $cookieData === null) {
$this->_setCookie($request, $response);
}
if ($request->is(['patch', 'put', 'post', 'delete'])) {
Expand All @@ -89,14 +96,19 @@ public function startup(Event $event) {
/**
* Set the cookie in the response.
*
* Also sets the request->params['_csrfToken'] so the newly minted
* token is available in the request data.
*
* @param Cake\Network\Request $request The request object.
* @param Cake\Network\Response $response The response object.
*/
protected function _setCookie(Request $request, Response $response) {
$settings = $this->settings;
$value = Security::hash(String::uuid(), 'sha1', true);
$request->params['_csrfToken'] = $value;
$response->cookie([
'name' => $settings['cookieName'],
'value' => Security::hash(String::uuid(), 'sha1', true),
'value' => $value,
'expiry' => $settings['expiry'],
'path' => $request->base,
]);
Expand Down
3 changes: 3 additions & 0 deletions Cake/Test/TestCase/Controller/Component/CsrfComponentTest.php
Expand Up @@ -69,6 +69,8 @@ public function testSettingCookie() {
$this->assertRegExp('/^[a-f0-9]+$/', $cookie['value'], 'Should look like a hash.');
$this->assertEquals(0, $cookie['expiry'], 'session duration.');
$this->assertEquals('/dir', $cookie['path'], 'session path.');

$this->assertEquals($cookie['value'], $controller->request->params['_csrfToken']);
}

/**
Expand Down Expand Up @@ -183,6 +185,7 @@ public function testCsrfValidationSkipsRequestAction() {
$event = new Event('Controller.startup', $controller);
$result = $this->component->startUp($event);
$this->assertNull($result, 'No error.');
$this->assertEquals('testing123', $controller->request->params['_csrfToken']);
}

/**
Expand Down

0 comments on commit fc6b93d

Please sign in to comment.