I'm using CakePHP 3.4 (can't upgrade) and in order to protect the system from Cross Site Request Forgery I need to set the CSRF token cookie to SameSite = Strict. However, it seems this version of CakePHP can't handle such setting.
I have tried using the CsrfComponent class and loading the component in AppController
$this->loadComponent('Csrf', [
'secure' => true,
'httpOnly' => true,
]);
How can I workaround setting this cookie to SameSite = Strict or another alternative to be protected from Cross Site Request Forgery?
In CakePHP 3.9.3 support for samesite with CSRF cookies has been added, you'd have to switch to the CSRF protection middleware though.
If you can't upgrade, then you'll a bit of custom code, namely a custom/extended CSRF component that accepts further options for the attribute, and a custom/exteneded response object that creates cookies with that attribute accordingly.
In PHP versions earlier than PHP 7.3, you can, respectively must inject theSameSite
attribute by utilizing the cookie path hack, which consists of appending further cookie attributes to the path, by simply closing the path of with a semicolon. In PHP versions as of PHP 7.3 you would use the as of then supportedsamesite
for .
btw, for session cookies you'd modify yoursession.cookie_path
orsession.cookie_samesite
PHP INI options accordingly, and other places in CakePHP that set cookies would possibly need to be adapted too, for example the , even if your app doesn't use it, it might be used by 3rd party plugins.
Example:
<?php
// in src/Controller/Component/CsrfComponent.php
namespace App\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\Http\Response;
use Cake\Http\ServerRequest;
class CsrfComponent extends \Cake\Controller\Component\CsrfComponent
{
public function __construct(ComponentRegistry $registry, array $config = [])
{
// Use Lax by default
$config += [
'samsite' => 'Lax',
];
parent::__construct($registry, $config);
}
protected function _setCookie(ServerRequest $request, Response $response)
{
parent::_setCookie($request, $response);
// Add samesite option to the cookie that has been created by the parent
$cookie = $response->cookie($this->getConfig('cookieName'));
$cookie['samesite'] = $this->getConfig('samesite');
$response->cookie($cookie);
}
}
https://github.com/cakephp/cakephp/blob/3.4.14/src/Controller/Component/CsrfComponent.php#L125
// in src/Http/Response.php
namespace App\Http;
class Response extends \Cake\Http\Response
{
protected function _setCookies()
{
foreach ($this->_cookies as $name => $c) {
if (version_compare(PHP_VERSION, '7.3.0', '<')) {
// Use regular syntax (with possible path hack) in case
// no samesite has been set, or the PHP version doesn't
// support the samesite option.
if (isset($c['samesite'])) {
$c['path'] .= '; SameSite=' . $c['samesite'];
}
setcookie(
$name,
$c['value'],
$c['expire'],
$c['path'],
$c['domain'],
$c['secure'],
$c['httpOnly']
);
} else {
setcookie($name, $c['value'], [
'expires' => $c['expire'],
'path' => $c['path'],
'domain' => $c['domain'],
'secure' => $c['secure'],
'httponly' => $c['httpOnly'],
'samesite' => $c['samesite'],
]);
}
}
}
}
https://github.com/cakephp/cakephp/blob/3.4.14/src/Http/Response.php#L540
Inject the custom response object in yourAppController
's constructor:
// in src/Controller/AppController.php
use Cake\Http\Response;
use Cake\Http\ServerRequest;
// ...
class AppController extends Controller
{
// ...
public function __construct(
ServerRequest $request = null,
Response $response = null,
$name = null,
$eventManager = null,
$components = null
) {
if ($response !== null) {
throw new \InvalidArgumentException(
'This should not happen, we want to use a custom response class.'
);
}
$response = new \App\Http\Response();
parent::__construct($request, $response, $name, $eventManager, $components);
}
// ...
}
Finally with the custom component class and set yoursamesite
config:
// in src/Controller/AppController.php
// ...
class AppController extends Controller
{
// ...
public function initialize()
{
parent::initialize();
// ...
$this->loadComponent('Csrf', [
'className' => \App\Controller\Component\CsrfComponent::class,
'secure' => true,
'httpOnly' => true,
'samesite' => 'Strict',
]);
}
// ...
}
On a closing note it should be noted that in later CakePHP 3.x versions the cookie arrays have been replaced with cookie objects, so that would require changes accordingly, but since you can't upgrade, this should be fine, and once you decide to upgrade, shoot for the stars and upgrade to the latest version.
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Find the answer in similar questions on our website.
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.
PHP (from the English Hypertext Preprocessor - hypertext preprocessor) is a scripting programming language for developing web applications. Supported by most hosting providers, it is one of the most popular tools for creating dynamic websites.
The PHP scripting language has gained wide popularity due to its processing speed, simplicity, cross-platform, functionality and distribution of source codes under its own license.
https://www.php.net/
CakePHP is a framework that has been around since 2005 and is known for the convenience it gives web developers. It needs very modest settings, does not require the use of XML or YAML files. It has its own ORM, which sets it apart from other similar tools. In terms of security, it is also doing well, in particular, it has a protection system against CSRF attacks.
https://cakephp.org/
Welcome to the Q&A site for web developers. Here you can ask a question about the problem you are facing and get answers from other experts. We have created a user-friendly interface so that you can quickly and free of charge ask a question about a web programming problem. We also invite other experts to join our community and help other members who ask questions. In addition, you can use our search for questions with a solution.
Ask about the real problem you are facing. Describe in detail what you are doing and what you want to achieve.
Our goal is to create a strong community in which everyone will support each other. If you find a question and know the answer to it, help others with your knowledge.