Skip to content

Commit 9624937

Browse files
committed
Merge remote-tracking branch 'origin/CABPI-470' into gl_pr_arrows_adobeims_sep20_2022
2 parents ab999dd + 3960a90 commit 9624937

File tree

2 files changed

+144
-6
lines changed

2 files changed

+144
-6
lines changed

app/code/Magento/AdobeIms/Model/Authorization.php

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77

88
namespace Magento\AdobeIms\Model;
99

10-
use Magento\AdobeImsApi\Api\ConfigInterface;
10+
use Laminas\Uri\Uri;
1111
use Magento\AdobeImsApi\Api\AuthorizationInterface;
12+
use Magento\AdobeImsApi\Api\ConfigInterface;
1213
use Magento\Framework\Exception\InvalidArgumentException;
1314
use Magento\Framework\HTTP\Client\Curl;
1415
use Magento\Framework\HTTP\Client\CurlFactory;
16+
use Magento\Framework\Stdlib\Parameters;
1517

1618
/**
1719
* Provide auth url and validate authorization
@@ -30,16 +32,37 @@ class Authorization implements AuthorizationInterface
3032
*/
3133
private CurlFactory $curlFactory;
3234

35+
/**
36+
* @var string|null
37+
*/
38+
private $redirectHost = null;
39+
40+
/**
41+
* @var Parameters
42+
*/
43+
private Parameters $parameters;
44+
45+
/**
46+
* @var Uri
47+
*/
48+
private Uri $uri;
49+
3350
/**
3451
* @param CurlFactory $curlFactory
3552
* @param ConfigInterface $imsConfig
53+
* @param Parameters $parameters
54+
* @param Uri $uri
3655
*/
3756
public function __construct(
3857
CurlFactory $curlFactory,
39-
ConfigInterface $imsConfig
58+
ConfigInterface $imsConfig,
59+
Parameters $parameters,
60+
Uri $uri
4061
) {
4162
$this->curlFactory = $curlFactory;
4263
$this->imsConfig = $imsConfig;
64+
$this->parameters = $parameters;
65+
$this->uri = $uri;
4366
}
4467

4568
/**
@@ -52,7 +75,10 @@ public function __construct(
5275
public function getAuthUrl(?string $clientId = null): string
5376
{
5477
$authUrl = $this->imsConfig->getAdminAdobeImsAuthUrl($clientId);
55-
return $this->getAuthorizationLocation($authUrl);
78+
$imsUrl = $this->getAuthorizationLocation($authUrl);
79+
$this->validateRedirectUrls($authUrl, $imsUrl);
80+
81+
return $imsUrl;
5682
}
5783

5884
/**
@@ -117,4 +143,48 @@ private function validateResponse(Curl $curl): void
117143
);
118144
}
119145
}
146+
147+
/**
148+
* Validate current host and IMS returned host to make sure credentials belongs to correct project.
149+
*
150+
* @param string $authUrl
151+
* @param string $imsUrl
152+
* @throws InvalidArgumentException
153+
*/
154+
private function validateRedirectUrls(string $authUrl, string $imsUrl)
155+
{
156+
$imsRedirectUrlHost = $this->getRedirectUrlHost($imsUrl);
157+
$currentRedirectHost = $this->getRedirectUrlHost($authUrl);
158+
if (!($imsRedirectUrlHost && $currentRedirectHost) || !($imsRedirectUrlHost === $currentRedirectHost)) {
159+
throw new InvalidArgumentException(
160+
__('Could not get a valid response from Adobe IMS Service.')
161+
);
162+
}
163+
}
164+
165+
/**
166+
* Get host from redirect Url
167+
*
168+
* @param string $imsUrl
169+
* @return string|null
170+
*/
171+
private function getRedirectUrlHost(string $imsUrl): ?string
172+
{
173+
$this->uri->parse($imsUrl);
174+
$this->parameters->fromString($this->uri->getQuery());
175+
$urlParams = $this->parameters->toArray();
176+
if (!isset($urlParams['redirect_uri'])) {
177+
foreach ($urlParams as $param => $value) {
178+
if ($param === 'callback' || $param === 'uc_callback') {
179+
$this->getRedirectUrlHost($value);
180+
} elseif ($this->redirectHost) {
181+
break;
182+
}
183+
}
184+
} elseif (isset($urlParams['redirect_uri'])) {
185+
$this->uri->parse($urlParams['redirect_uri']);
186+
$this->redirectHost = $this->uri->getHost();
187+
}
188+
return $this->redirectHost;
189+
}
120190
}

app/code/Magento/AdobeIms/Test/Unit/Model/GetAuthorizationUrlTest.php renamed to app/code/Magento/AdobeIms/Test/Unit/Model/AuthorizationTest.php

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77

88
namespace Magento\AdobeIms\Test\Unit\Model;
99

10+
use Laminas\Uri\Uri;
1011
use Magento\AdobeIms\Model\Authorization;
1112
use Magento\AdobeImsApi\Api\ConfigInterface;
1213
use Magento\Framework\Exception\InvalidArgumentException;
1314
use Magento\Framework\HTTP\Client\Curl;
1415
use Magento\Framework\HTTP\Client\CurlFactory;
16+
use Magento\Framework\Stdlib\Parameters;
1517
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
1618
use PHPUnit\Framework\TestCase;
1719

18-
class GetAuthorizationUrlTest extends TestCase
20+
class AuthorizationTest extends TestCase
1921
{
2022
private const AUTH_URL = 'https://adobe-login-url.com/authorize' .
2123
'?client_id=AdobeCommerceIMS' .
@@ -26,6 +28,8 @@ class GetAuthorizationUrlTest extends TestCase
2628

2729
private const AUTH_URL_ERROR = 'https://adobe-login-url.com/authorize?error=invalid_scope';
2830

31+
private const REDIRECT_URL = 'https://magento-instance.local';
32+
2933
/**
3034
* @var CurlFactory
3135
*/
@@ -35,6 +39,14 @@ class GetAuthorizationUrlTest extends TestCase
3539
* @var Authorization
3640
*/
3741
private $authorizationUrl;
42+
/**
43+
* @var Parameters|\PHPUnit\Framework\MockObject\MockObject
44+
*/
45+
private mixed $parametersMock;
46+
/**
47+
* @var Parameters|\PHPUnit\Framework\MockObject\MockObject
48+
*/
49+
private mixed $uriMock;
3850

3951
protected function setUp(): void
4052
{
@@ -45,16 +57,69 @@ protected function setUp(): void
4557
->method('getAuthUrl')
4658
->willReturn(self::AUTH_URL);
4759
$this->curlFactory = $this->createMock(CurlFactory::class);
48-
60+
$this->parametersMock = $this->createMock(Parameters::class);
61+
$this->uriMock = $this->createMock(Uri::class);
62+
$urlParts = [];
63+
$url = self::AUTH_URL;
64+
$this->uriMock->expects($this->any())
65+
->method('parse')
66+
->willReturnCallback(
67+
function ($url) use (&$urlParts) {
68+
$urlParts = parse_url($url);
69+
}
70+
);
71+
$this->uriMock->expects($this->any())
72+
->method('getHost')
73+
->willReturnCallback(
74+
function () use (&$urlParts) {
75+
return array_key_exists('host', $urlParts) ? $urlParts['host'] : '';
76+
}
77+
);
78+
$this->uriMock->expects($this->any())
79+
->method('getQuery')
80+
->willReturnCallback(
81+
function () {
82+
return 'callback=' . self::REDIRECT_URL;
83+
}
84+
);
85+
$this->parametersMock->method('fromString')
86+
->with('callback=' . self::REDIRECT_URL)
87+
->willReturnSelf();
88+
$this->parametersMock->method('toArray')
89+
->willReturn([
90+
'redirect_uri' => self::REDIRECT_URL
91+
]);
4992
$this->authorizationUrl = $objectManagerHelper->getObject(
5093
Authorization::class,
5194
[
5295
'curlFactory' => $this->curlFactory,
53-
'imsConfig' => $imsConfigMock
96+
'imsConfig' => $imsConfigMock,
97+
'parameters' => $this->parametersMock,
98+
'uri' => $this->uriMock
5499
]
55100
);
56101
}
57102

103+
/**
104+
* Test IMS host belongs to correct project
105+
*/
106+
public function testAuthUrlValidateImsHostBelongsToCorrectProject(): void
107+
{
108+
$curlMock = $this->createMock(Curl::class);
109+
$curlMock->method('getHeaders')
110+
->willReturn(['location' => self::AUTH_URL]);
111+
$curlMock->method('getStatus')
112+
->willReturn(302);
113+
114+
$this->curlFactory->method('create')
115+
->willReturn($curlMock);
116+
117+
$this->assertEquals($this->authorizationUrl->getAuthUrl(), self::AUTH_URL);
118+
}
119+
120+
/**
121+
* Test auth throws exception code when response code is 200
122+
*/
58123
public function testAuthThrowsExceptionWhenResponseCodeIs200(): void
59124
{
60125
$curlMock = $this->createMock(Curl::class);
@@ -71,6 +136,9 @@ public function testAuthThrowsExceptionWhenResponseCodeIs200(): void
71136
$this->authorizationUrl->getAuthUrl();
72137
}
73138

139+
/**
140+
* Test auth throws exception code when response contains error
141+
*/
74142
public function testAuthThrowsExceptionWhenResponseContainsError(): void
75143
{
76144
$curlMock = $this->createMock(Curl::class);

0 commit comments

Comments
 (0)