Skip to content

Commit 26b9eee

Browse files
authored
Adds support for "SameSite" cookie property (#1246)
* Support SameSite cookie property (fixes issue #414) * Support SameSite cookie property (fixes issue #414) * Open in new tab * Default fallback to None just in case someone forgets to clear cache * * Force secure if SameSite None * SameSite consistency for renew and delete functions * Code formatting #OCD :) * PHP 7.0 compatibility * Fix pipeline errors * Removed incorrect copyright docs
1 parent 0aec67d commit 26b9eee

File tree

5 files changed

+81
-20
lines changed

5 files changed

+81
-20
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
class Mage_Adminhtml_Model_System_Config_Source_Cookie_SameSite
4+
{
5+
/**
6+
* @return array[]
7+
*/
8+
public function toOptionArray(): array
9+
{
10+
return [
11+
['value' => 'None', 'label' => Mage::helper('adminhtml')->__('None')],
12+
['value' => 'Strict', 'label' => Mage::helper('adminhtml')->__('Strict')],
13+
['value' => 'Lax', 'label' => Mage::helper('adminhtml')->__('Lax')]
14+
];
15+
}
16+
}

app/code/core/Mage/Core/Model/Cookie.php

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Mage_Core_Model_Cookie
3737
const XML_PATH_COOKIE_PATH = 'web/cookie/cookie_path';
3838
const XML_PATH_COOKIE_LIFETIME = 'web/cookie/cookie_lifetime';
3939
const XML_PATH_COOKIE_HTTPONLY = 'web/cookie/cookie_httponly';
40+
const XML_PATH_COOKIE_SAMESITE = 'web/cookie/cookie_samesite';
4041

4142
protected $_lifetime;
4243

@@ -174,6 +175,20 @@ public function getHttponly()
174175
return (bool)$httponly;
175176
}
176177

178+
/**
179+
* Retrieve use SameSite
180+
*
181+
* @return string
182+
*/
183+
public function getSameSite(): string
184+
{
185+
$sameSite = Mage::getStoreConfig(self::XML_PATH_COOKIE_SAMESITE, $this->getStore());
186+
if (is_null($sameSite)) {
187+
return 'None';
188+
}
189+
return (string)$sameSite;
190+
}
191+
177192
/**
178193
* Is https secure request
179194
* Use secure on adminhtml only
@@ -202,9 +217,10 @@ public function isSecure()
202217
* @param string $domain
203218
* @param int|bool $secure
204219
* @param bool $httponly
220+
* @param string $sameSite
205221
* @return $this
206222
*/
207-
public function set($name, $value, $period = null, $path = null, $domain = null, $secure = null, $httponly = null)
223+
public function set($name, $value, $period = null, $path = null, $domain = null, $secure = null, $httponly = null, $sameSite = null)
208224
{
209225
/**
210226
* Check headers sent
@@ -236,8 +252,34 @@ public function set($name, $value, $period = null, $path = null, $domain = null,
236252
if (is_null($httponly)) {
237253
$httponly = $this->getHttponly();
238254
}
255+
if (is_null($sameSite)) {
256+
$sameSite = $this->getSameSite();
257+
}
239258

240-
setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
259+
if ($sameSite === 'None') {
260+
// Enforce specification SameSite None requires secure
261+
$secure = true;
262+
}
263+
264+
if (PHP_VERSION_ID >= 70300) {
265+
setcookie(
266+
$name,
267+
$value,
268+
[
269+
'expires' => $expire,
270+
'path' => $path,
271+
'domain' => $domain,
272+
'secure' => $secure,
273+
'httponly' => $httponly,
274+
'samesite' => $sameSite
275+
]
276+
);
277+
} else {
278+
if (!empty($sameSite)) {
279+
$path.= "; samesite=${sameSite}";
280+
}
281+
setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
282+
}
241283

242284
return $this;
243285
}
@@ -251,16 +293,17 @@ public function set($name, $value, $period = null, $path = null, $domain = null,
251293
* @param string $domain
252294
* @param int|bool $secure
253295
* @param bool $httponly
296+
* @param string $sameSite
254297
* @return $this
255298
*/
256-
public function renew($name, $period = null, $path = null, $domain = null, $secure = null, $httponly = null)
299+
public function renew($name, $period = null, $path = null, $domain = null, $secure = null, $httponly = null, $sameSite = null)
257300
{
258301
if (($period === null) && !$this->getLifetime()) {
259302
return $this;
260303
}
261304
$value = $this->_getRequest()->getCookie($name, false);
262305
if ($value !== false) {
263-
$this->set($name, $value, $period, $path, $domain, $secure, $httponly);
306+
$this->set($name, $value, $period, $path, $domain, $secure, $httponly, $sameSite);
264307
}
265308
return $this;
266309
}
@@ -284,9 +327,10 @@ public function get($name = null)
284327
* @param string $domain
285328
* @param int|bool $secure
286329
* @param int|bool $httponly
330+
* @param string $sameSite
287331
* @return $this
288332
*/
289-
public function delete($name, $path = null, $domain = null, $secure = null, $httponly = null)
333+
public function delete($name, $path = null, $domain = null, $secure = null, $httponly = null, $sameSite = null)
290334
{
291335
/**
292336
* Check headers sent
@@ -295,20 +339,6 @@ public function delete($name, $path = null, $domain = null, $secure = null, $htt
295339
return $this;
296340
}
297341

298-
if (is_null($path)) {
299-
$path = $this->getPath();
300-
}
301-
if (is_null($domain)) {
302-
$domain = $this->getDomain();
303-
}
304-
if (is_null($secure)) {
305-
$secure = $this->isSecure();
306-
}
307-
if (is_null($httponly)) {
308-
$httponly = $this->getHttponly();
309-
}
310-
311-
setcookie($name, null, null, $path, $domain, $secure, $httponly);
312-
return $this;
342+
return $this->set($name, null, null, $path, $domain, $secure, $httponly, $sameSite);
313343
}
314344
}

app/code/core/Mage/Core/etc/config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@
407407
<cookie>
408408
<cookie_lifetime>3600</cookie_lifetime>
409409
<cookie_httponly>1</cookie_httponly>
410+
<cookie_samesite>None</cookie_samesite>
410411
<cookie_restriction>0</cookie_restriction>
411412
<cookie_restriction_lifetime>31536000</cookie_restriction_lifetime>
412413
</cookie>

app/code/core/Mage/Core/etc/system.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,16 @@
15741574
<show_in_website>1</show_in_website>
15751575
<show_in_store>1</show_in_store>
15761576
</cookie_httponly>
1577+
<cookie_samesite translate="label">
1578+
<label>Same-Site</label>
1579+
<frontend_type>select</frontend_type>
1580+
<source_model>adminhtml/system_config_source_cookie_samesite</source_model>
1581+
<comment><![CDATA[<a target="_blank" href="https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00"/>https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00</a>]]></comment>
1582+
<sort_order>45</sort_order>
1583+
<show_in_default>1</show_in_default>
1584+
<show_in_website>1</show_in_website>
1585+
<show_in_store>1</show_in_store>
1586+
</cookie_samesite>
15771587
<cookie_restriction translate="label">
15781588
<label>Cookie Restriction Mode</label>
15791589
<frontend_type>select</frontend_type>

app/locale/en_US/Mage_Core.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@
397397
"Use Custom Admin Path","Use Custom Admin Path"
398398
"Use Custom Admin URL","Use Custom Admin URL"
399399
"Use HTTP Only","Use HTTP Only"
400+
"Same-Site","Same-Site"
401+
"None","None"
402+
"Strict","Strict"
403+
"Lax","Lax"
400404
"Use SID on Frontend","Use SID on Frontend"
401405
"Use Secure URLs in Admin","Use Secure URLs in Admin"
402406
"Use Secure URLs in Frontend","Use Secure URLs in Frontend"

0 commit comments

Comments
 (0)