Skip to content

Commit a0670fb

Browse files
committed
Merge branch 'MC-38366' of github.com:magento-cia/magento2ce into cia-2.3.7-1152021
2 parents 10df823 + d674d42 commit a0670fb

File tree

9 files changed

+279
-100
lines changed

9 files changed

+279
-100
lines changed

app/code/Magento/Backend/Model/Auth/Session.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Backend\Model\Auth;
79

810
use Magento\Framework\App\ObjectManager;
@@ -210,7 +212,8 @@ public function prolong()
210212
->setPath($this->sessionConfig->getCookiePath())
211213
->setDomain($this->sessionConfig->getCookieDomain())
212214
->setSecure($this->sessionConfig->getCookieSecure())
213-
->setHttpOnly($this->sessionConfig->getCookieHttpOnly());
215+
->setHttpOnly($this->sessionConfig->getCookieHttpOnly())
216+
->setSameSite($this->sessionConfig->getCookieSameSite());
214217
$this->cookieManager->setPublicCookie($this->getName(), $cookieValue, $cookieMetadata);
215218
}
216219
}

app/code/Magento/Backend/Model/Session/AdminConfig.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public function __construct(
8585
$this->setCookiePath($adminPath);
8686
$this->setName($sessionName);
8787
$this->setCookieSecure($this->_httpRequest->isSecure());
88+
$this->setCookieSameSite('Lax');
8889
}
8990

9091
/**
@@ -96,6 +97,7 @@ private function extractAdminPath()
9697
{
9798
$backendApp = $this->backendAppList->getCurrentApp();
9899
$cookiePath = null;
100+
//phpcs:ignore
99101
$baseUrl = parse_url($this->backendUrlFactory->create()->getBaseUrl(), PHP_URL_PATH);
100102
if (!$backendApp) {
101103
$cookiePath = $baseUrl . $this->_frontNameResolver->getFrontName();

app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,58 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Backend\Test\Unit\Model\Auth;
79

10+
use Magento\Backend\App\Config;
811
use Magento\Backend\Model\Auth\Session;
12+
use Magento\Framework\Acl;
13+
use Magento\Framework\Acl\Builder;
14+
use Magento\Framework\Session\Storage;
15+
use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
16+
use Magento\Framework\Stdlib\Cookie\PhpCookieManager;
17+
use Magento\Framework\Stdlib\Cookie\PublicCookieMetadata;
18+
use Magento\Framework\Stdlib\CookieManagerInterface;
919
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
20+
use Magento\User\Model\User;
21+
use PHPUnit\Framework\MockObject\MockObject;
22+
use PHPUnit\Framework\TestCase;
1023

1124
/**
1225
* Class SessionTest tests Magento\Backend\Model\Auth\Session
1326
*
1427
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1528
*/
16-
class SessionTest extends \PHPUnit\Framework\TestCase
29+
class SessionTest extends TestCase
1730
{
1831
/**
19-
* @var \Magento\Backend\App\Config | \PHPUnit_Framework_MockObject_MockObject
32+
* @var Config|MockObject
2033
*/
2134
private $config;
2235

2336
/**
24-
* @var \Magento\Framework\Session\Config | \PHPUnit_Framework_MockObject_MockObject
37+
* @var \Magento\Framework\Session\Config|MockObject
2538
*/
2639
private $sessionConfig;
2740

2841
/**
29-
* @var \Magento\Framework\Stdlib\CookieManagerInterface | \PHPUnit_Framework_MockObject_MockObject
42+
* @var CookieManagerInterface|MockObject
3043
*/
3144
private $cookieManager;
3245

3346
/**
34-
* @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory | \PHPUnit_Framework_MockObject_MockObject
47+
* @var CookieMetadataFactory|MockObject
3548
*/
3649
private $cookieMetadataFactory;
3750

3851
/**
39-
* @var \Magento\Framework\Session\Storage | \PHPUnit_Framework_MockObject_MockObject
52+
* @var Storage|MockObject
4053
*/
4154
private $storage;
4255

4356
/**
44-
* @var \Magento\Framework\Acl\Builder | \PHPUnit_Framework_MockObject_MockObject
57+
* @var Builder|MockObject
4558
*/
4659
private $aclBuilder;
4760

@@ -53,32 +66,38 @@ class SessionTest extends \PHPUnit\Framework\TestCase
5366
/**
5467
* @inheritdoc
5568
*/
56-
protected function setUp()
69+
protected function setUp(): void
5770
{
5871
$this->cookieMetadataFactory = $this->createPartialMock(
59-
\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class,
72+
CookieMetadataFactory::class,
6073
['createPublicCookieMetadata']
6174
);
6275

63-
$this->config = $this->createPartialMock(\Magento\Backend\App\Config::class, ['getValue']);
76+
$this->config = $this->createPartialMock(Config::class, ['getValue']);
6477
$this->cookieManager = $this->createPartialMock(
65-
\Magento\Framework\Stdlib\Cookie\PhpCookieManager::class,
78+
PhpCookieManager::class,
6679
['getCookie', 'setPublicCookie']
6780
);
6881
$this->storage = $this->createPartialMock(
69-
\Magento\Framework\Session\Storage::class,
82+
Storage::class,
7083
['getUser', 'getAcl', 'setAcl']
7184
);
7285
$this->sessionConfig = $this->createPartialMock(
7386
\Magento\Framework\Session\Config::class,
74-
['getCookiePath', 'getCookieDomain', 'getCookieSecure', 'getCookieHttpOnly']
87+
[
88+
'getCookiePath',
89+
'getCookieDomain',
90+
'getCookieSecure',
91+
'getCookieHttpOnly',
92+
'getCookieSameSite'
93+
]
7594
);
76-
$this->aclBuilder = $this->getMockBuilder(\Magento\Framework\Acl\Builder::class)
95+
$this->aclBuilder = $this->getMockBuilder(Builder::class)
7796
->disableOriginalConstructor()
7897
->getMock();
7998
$objectManager = new ObjectManager($this);
8099
$this->session = $objectManager->getObject(
81-
\Magento\Backend\Model\Auth\Session::class,
100+
Session::class,
82101
[
83102
'config' => $this->config,
84103
'sessionConfig' => $this->sessionConfig,
@@ -90,7 +109,7 @@ protected function setUp()
90109
);
91110
}
92111

93-
protected function tearDown()
112+
protected function tearDown(): void
94113
{
95114
$this->config = null;
96115
$this->sessionConfig = null;
@@ -103,9 +122,11 @@ protected function tearDown()
103122
*/
104123
public function testRefreshAcl($isUserPassedViaParams)
105124
{
106-
$aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock();
125+
$aclMock = $this->getMockBuilder(Acl::class)
126+
->disableOriginalConstructor()
127+
->getMock();
107128
$this->aclBuilder->expects($this->any())->method('getAcl')->willReturn($aclMock);
108-
$userMock = $this->getMockBuilder(\Magento\User\Model\User::class)
129+
$userMock = $this->getMockBuilder(User::class)
109130
->setMethods(['getReloadAclFlag', 'setReloadAclFlag', 'unsetData', 'save'])
110131
->disableOriginalConstructor()
111132
->getMock();
@@ -136,14 +157,14 @@ public function refreshAclDataProvider()
136157

137158
public function testIsLoggedInPositive()
138159
{
139-
$user = $this->createPartialMock(\Magento\User\Model\User::class, ['getId', '__wakeup']);
160+
$user = $this->createPartialMock(User::class, ['getId', '__wakeup']);
140161
$user->expects($this->once())
141162
->method('getId')
142-
->will($this->returnValue(1));
163+
->willReturn(1);
143164

144165
$this->storage->expects($this->any())
145166
->method('getUser')
146-
->will($this->returnValue($user));
167+
->willReturn($user);
147168

148169
$this->assertTrue($this->session->isLoggedIn());
149170
}
@@ -160,54 +181,55 @@ public function testProlong()
160181

161182
$this->config->expects($this->once())
162183
->method('getValue')
163-
->with(\Magento\Backend\Model\Auth\Session::XML_PATH_SESSION_LIFETIME)
184+
->with(Session::XML_PATH_SESSION_LIFETIME)
164185
->willReturn($lifetime);
165-
$cookieMetadata = $this->createMock(\Magento\Framework\Stdlib\Cookie\PublicCookieMetadata::class);
186+
$cookieMetadata = $this->createMock(PublicCookieMetadata::class);
166187
$cookieMetadata->expects($this->once())
167188
->method('setDuration')
168-
->with($lifetime)
169-
->will($this->returnSelf());
189+
->with($lifetime)->willReturnSelf();
170190
$cookieMetadata->expects($this->once())
171191
->method('setPath')
172-
->with($path)
173-
->will($this->returnSelf());
192+
->with($path)->willReturnSelf();
174193
$cookieMetadata->expects($this->once())
175194
->method('setDomain')
176-
->with($domain)
177-
->will($this->returnSelf());
195+
->with($domain)->willReturnSelf();
178196
$cookieMetadata->expects($this->once())
179197
->method('setSecure')
180-
->with($secure)
181-
->will($this->returnSelf());
198+
->with($secure)->willReturnSelf();
182199
$cookieMetadata->expects($this->once())
183200
->method('setHttpOnly')
184-
->with($httpOnly)
185-
->will($this->returnSelf());
201+
->with($httpOnly)->willReturnSelf();
202+
$cookieMetadata->expects($this->once())
203+
->method('setSameSite')
204+
->willReturnSelf();
186205

187206
$this->cookieMetadataFactory->expects($this->once())
188207
->method('createPublicCookieMetadata')
189-
->will($this->returnValue($cookieMetadata));
208+
->willReturn($cookieMetadata);
190209

191210
$this->cookieManager->expects($this->once())
192211
->method('getCookie')
193212
->with($name)
194-
->will($this->returnValue($cookie));
213+
->willReturn($cookie);
195214
$this->cookieManager->expects($this->once())
196215
->method('setPublicCookie')
197216
->with($name, $cookie, $cookieMetadata);
198217

199218
$this->sessionConfig->expects($this->once())
200219
->method('getCookiePath')
201-
->will($this->returnValue($path));
220+
->willReturn($path);
202221
$this->sessionConfig->expects($this->once())
203222
->method('getCookieDomain')
204-
->will($this->returnValue($domain));
223+
->willReturn($domain);
205224
$this->sessionConfig->expects($this->once())
206225
->method('getCookieSecure')
207-
->will($this->returnValue($secure));
226+
->willReturn($secure);
208227
$this->sessionConfig->expects($this->once())
209228
->method('getCookieHttpOnly')
210-
->will($this->returnValue($httpOnly));
229+
->willReturn($httpOnly);
230+
$this->sessionConfig->expects($this->once())
231+
->method('getCookieSameSite')
232+
->willReturn('Lax');
211233

212234
$this->session->prolong();
213235

@@ -225,15 +247,21 @@ public function testIsAllowed($isUserDefined, $isAclDefined, $isAllowed, $expect
225247
{
226248
$userAclRole = 'userAclRole';
227249
if ($isAclDefined) {
228-
$aclMock = $this->getMockBuilder(\Magento\Framework\Acl::class)->disableOriginalConstructor()->getMock();
250+
$aclMock = $this->getMockBuilder(Acl::class)
251+
->disableOriginalConstructor()
252+
->getMock();
229253
$this->storage->expects($this->any())->method('getAcl')->willReturn($aclMock);
230254
}
231255
if ($isUserDefined) {
232-
$userMock = $this->getMockBuilder(\Magento\User\Model\User::class)->disableOriginalConstructor()->getMock();
256+
$userMock = $this->getMockBuilder(User::class)
257+
->disableOriginalConstructor()
258+
->getMock();
233259
$this->storage->expects($this->once())->method('getUser')->willReturn($userMock);
234260
}
235261
if ($isAclDefined && $isUserDefined) {
262+
// phpstan:ignore
236263
$userMock->expects($this->any())->method('getAclRole')->willReturn($userAclRole);
264+
// phpstan:ignore
237265
$aclMock->expects($this->once())->method('isAllowed')->with($userAclRole)->willReturn($isAllowed);
238266
}
239267

dev/tests/integration/testsuite/Magento/Framework/Session/ConfigTest.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67
// @codingStandardsIgnoreStart
78
namespace {
89
$mockPHPFunctions = false;
@@ -34,6 +35,7 @@ function ini_get($varName)
3435
} elseif ($mockPHPFunctions == 2) {
3536
return null;
3637
}
38+
//phpcs:ignore PHPCompatibility
3739
return call_user_func_array('\ini_get', func_get_args());
3840
}
3941

@@ -181,7 +183,7 @@ public function testSettingInvalidCookieLifetime()
181183
$model->setCookieLifetime('foobar_bogus');
182184
$this->assertEquals($preVal, $model->getCookieLifetime());
183185
}
184-
186+
185187
public function testSettingInvalidCookieLifetime2()
186188
{
187189
$model = $this->getModel();
@@ -375,5 +377,18 @@ private function getModel(): \Magento\Framework\Session\Config
375377
['deploymentConfig' => $this->deploymentConfigMock]
376378
);
377379
}
380+
381+
/**
382+
* Test Set SameSite Attribute
383+
*
384+
* @return void
385+
*/
386+
public function testSetCookieInvalidSameSite(): void
387+
{
388+
$model = $this->getModel();
389+
$this->expectException('InvalidArgumentException');
390+
$this->expectExceptionMessage('Invalid Samesite attribute.');
391+
$model->setCookieSameSite('foobar');
392+
}
378393
}
379394
}

lib/internal/Magento/Framework/Session/Config.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
* Copyright © Magento, Inc. All rights reserved.
66
* See COPYING.txt for license details.
77
*/
8+
declare(strict_types=1);
9+
810
namespace Magento\Framework\Session;
911

1012
use Magento\Framework\App\DeploymentConfig;
1113
use Magento\Framework\App\Filesystem\DirectoryList;
1214
use Magento\Framework\Filesystem;
1315
use Magento\Framework\Session\Config\ConfigInterface;
16+
use Magento\Framework\Session\Config\Validator\CookieSameSiteValidator;
1417

1518
/**
1619
* Magento session configuration
@@ -208,6 +211,7 @@ public function __construct(
208211
$unsecureURL = $this->_scopeConfig->getValue('web/unsecure/base_url', $this->_scopeType);
209212
$isFullySecuredURL = $secureURL == $unsecureURL;
210213
$this->setCookieSecure($isFullySecuredURL && $this->_httpRequest->isSecure());
214+
$this->setCookieSameSite('Lax');
211215
}
212216

213217
/**
@@ -572,4 +576,36 @@ public function __call($method, $args)
572576
throw new \BadMethodCallException(sprintf('Method "%s" does not exist in %s', $method, get_class($this)));
573577
}
574578
}
579+
580+
/**
581+
* Set session.cookie_samesite
582+
*
583+
* @param string $cookieSameSite
584+
* @return $this
585+
*/
586+
public function setCookieSameSite(string $cookieSameSite = 'Lax'): ConfigInterface
587+
{
588+
$validator = $this->_validatorFactory->create(
589+
[],
590+
CookieSameSiteValidator::class
591+
);
592+
if (!$validator->isValid($cookieSameSite) ||
593+
!$this->getCookieSecure() && strtolower($cookieSameSite) === 'none') {
594+
throw new \InvalidArgumentException(
595+
'Invalid Samesite attribute.'
596+
);
597+
}
598+
$this->setOption('session.cookie_samesite', $cookieSameSite);
599+
return $this;
600+
}
601+
602+
/**
603+
* Get session.cookie_samesite
604+
*
605+
* @return string
606+
*/
607+
public function getCookieSameSite(): string
608+
{
609+
return (string)$this->getOption('session.cookie_samesite');
610+
}
575611
}

0 commit comments

Comments
 (0)