Let me suggest to support same-site attribute through $config['cookie_samesite']
That's cool, but there's some issues around it ... For one, right now we just proxy to setcookie() and SameSite isn't supported on it until PHP 7.3.0; it's even trickier with sessions.
Do you have ideas about how it should ideally work?
Hi @narfbg Andrey, If I understand your question, Samesite is a very cheap way of preventing CSRF attack. But it will break if a web site has multiple subdomains to communicate for its authenticated contents.
No ... I'm very well aware of what the SameSite attribute is and what it does.
What I'm asking is how would you implement it in CI?
It would be a very useful thing. I have applications that make CORS calls to each other.
Google in April 2020 will need SameSite cookies = none. https://www.chromestatus.com/feature/5633521622188032

A cookie associated with a cross-site resource at <URL> was set without theSameSiteattribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set withSameSite=NoneandSecure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at <URL> and <URL>
I see that session is already doing some php version checks like is_php(XXX), so why not using the same technique to identify the php version which supports this natively (e.g. 7.3) and implement it into the setcookie() call.
I guess that makes sense for sessions, though I'm not sure if I'd want that to be configurable at all there.
Tell you what - it's up for grabs and anyone who wants this should submit a pull request with an implementation.
Referencing it properly, so the threads get linked: #5874
if you have same issue like am having in shopify app written with CI
upgrade the php version 7.3.x and in your config file add these two lines will fix the issue in your config.php :
<?php
/*config.php*/
defined('BASEPATH') or exit('No direct script access allowed');
ini_set('session.cookie_samesite', 'None');
ini_set('session.cookie_secure', TRUE);
harmandeep-singh solution worked for me. (I am making CORS request) and Chrome Android samesite update broke my website in that browser, thanks Google!
I had this same CORS problem in my application. my PHP 7.2 and my CI 3.X.
I was able to resolve it by making only the following change to the applications / config / config.php file
$config['cookie_path'] = '/; SameSite=None';
I had this same CORS problem in my application. my PHP 7.2 and my CI 3.X.
I was able to resolve it by making only the following change to the applications / config / config.php file$config['cookie_path'] = '/; SameSite=None';
That gives this Warning on PHP 7.3:
PHP Warning: Cookie paths cannot contain any of the following ',; \t\r\n\013\014' in ...system\core\Security.php:281
I had this same CORS problem in my application. my PHP 7.2 and my CI 3.X.
I was able to resolve it by making only the following change to the applications / config / config.php file
$config['cookie_path'] = '/; SameSite=None';That gives this Warning on PHP 7.3:
PHP Warning: Cookie paths cannot contain any of the following ',; \t\r\n\013\014' in ...system\core\Security.php:281
@MichalSkoula if that is case try another solution :
ini_set('session.cookie_samesite', 'None');
ini_set('session.cookie_secure', TRUE);
@harmandeep-singh this solution works for non-ajax requests but when one ajax request occurs, then session library overwrites cookie and removes samesite attribute. (line 163)
The above works great for the session cookie but not csrf. the LAST 2 answers to this stackexchange are the current solution if you need both session and csrf: https://stackoverflow.com/questions/60634341/codeigniter-3-samesite-attribute-for-csrf-protection
unless there's another config setting that affects csrf samesite I'm not seeing mentioned anywhere.
Maybe like this?
/*
|--------------------------------------------------------------------------
| Cookie Related Variables
|--------------------------------------------------------------------------
|
| 'cookie_prefix' = Set a cookie name prefix if you need to avoid collisions
| 'cookie_domain' = Set to .your-domain.com for site-wide cookies
| 'cookie_path' = Typically will be a forward slash
| 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists.
| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)
| 'cookie_samesite' = The SameSite cookie setting (Possible values: 'Lax', 'Strict', 'None', NULL, default: NULL)
|
| Note: These settings (with the exception of 'cookie_prefix' and
| 'cookie_httponly') will also affect sessions.
|
*/
$config['cookie_prefix'] = '';
$config['cookie_domain'] = '';
$config['cookie_path'] = '/';
$config['cookie_secure'] = FALSE;
$config['cookie_httponly'] = FALSE;
$config['cookie_samesite'] = NULL;
/**
* Set cookie
*
* Accepts an arbitrary number of parameters (up to 7) or an associative
* array in the first parameter containing all the values.
*
* @param string|mixed[] $name Cookie name or an array containing parameters
* @param string $value Cookie value
* @param int $expire Cookie expiration time in seconds
* @param string $domain Cookie domain (e.g.: '.yourdomain.com')
* @param string $path Cookie path (default: '/')
* @param string $prefix Cookie name prefix
* @param bool $secure Whether to only transfer cookies via SSL
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
* @param string|NULL $samesite The SameSite cookie setting (Possible values: 'Lax', 'Strict', 'None', NULL, default: NULL)
* @return void
*/
public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL)
{
if (is_array($name))
{
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
{
if (isset($name[$item]))
{
$$item = $name[$item];
}
}
}
if ($prefix === '' && config_item('cookie_prefix') !== '')
{
$prefix = config_item('cookie_prefix');
}
if ($domain == '' && config_item('cookie_domain') != '')
{
$domain = config_item('cookie_domain');
}
if ($path === '/' && config_item('cookie_path') !== '/')
{
$path = config_item('cookie_path');
}
$secure = ($secure === NULL && config_item('cookie_secure') !== NULL)
? (bool) config_item('cookie_secure')
: (bool) $secure;
$httponly = ($httponly === NULL && config_item('cookie_httponly') !== NULL)
? (bool) config_item('cookie_httponly')
: (bool) $httponly;
if ( ! is_numeric($expire) OR $expire < 0)
{
$expire = 1;
}
else
{
$expire = ($expire > 0) ? time() + $expire : 0;
}
if ($samesite === '' && config_item('cookie_samesite') !== '')
{
$samesite = config_item('cookie_samesite');
}
$samesite = is_string($samesite) ? ucfirst($samesite) : $samesite;
if ( ! in_array($samesite, array('Lax', 'Strict', 'None', NULL), true))
{
show_error("The SameSite cookie setting should be one of: 'Lax', 'Strict', 'None' or NULL.");
}
// Issue: https://github.com/bcit-ci/CodeIgniter/issues/5791
// Reference: https://stackoverflow.com/questions/39750906/php-setcookie-samesite-strict
if (PHP_VERSION_ID < 70300) {
setcookie(
$prefix.$name,
$value,
$expire,
$path.'; samesite='.$samesite,
$domain,
$secure,
$httponly
);
} else {
setcookie(
$prefix.$name,
$value,
array(
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
)
);
}
}
@esyede where do you put this solution please?
@otengkwame First code is for the application/config/config.php file. This lines:
https://github.com/bcit-ci/CodeIgniter/blob/0648ae2acb3fae84f2cc49e15edb345ccef6cad5/application/config/config.php#L378-L397
And the second one is for system/core/Input.php. This lines:
https://github.com/bcit-ci/CodeIgniter/blob/0648ae2acb3fae84f2cc49e15edb345ccef6cad5/system/core/Input.php#L289-L352
Just replace those config and the set_cookie method
Thanks so much @esyede
@otengkwame no problem
Most helpful comment
@otengkwame First code is for the
application/config/config.phpfile. This lines:https://github.com/bcit-ci/CodeIgniter/blob/0648ae2acb3fae84f2cc49e15edb345ccef6cad5/application/config/config.php#L378-L397
And the second one is for
system/core/Input.php. This lines:https://github.com/bcit-ci/CodeIgniter/blob/0648ae2acb3fae84f2cc49e15edb345ccef6cad5/system/core/Input.php#L289-L352
Just replace those config and the set_cookie method