Skip to content

Commit d69329c

Browse files
committed
ACP2E-2969: REST API unable to make requests with slash (/) in SKU when using Oauth1
- overridden laminas sign method
1 parent 8166480 commit d69329c

File tree

3 files changed

+57
-103
lines changed

3 files changed

+57
-103
lines changed

composer.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@
8989
"tubalmartin/cssmin": "^4.1",
9090
"web-token/jwt-framework": "^3.1",
9191
"webonyx/graphql-php": "^15.0",
92-
"wikimedia/less.php": "^3.2",
93-
"guzzlehttp/oauth-subscriber": "^0.6"
92+
"wikimedia/less.php": "^3.2"
9493
},
9594
"require-dev": {
9695
"allure-framework/allure-phpunit": "^2",

lib/internal/Magento/Framework/Oauth/Helper/HmacSignature.php renamed to lib/internal/Magento/Framework/Oauth/Helper/Utility.php

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
<?php
22
/************************************************************************
33
*
4-
* ADOBE CONFIDENTIAL
5-
* ___________________
6-
*
7-
* Copyright 2023 Adobe
4+
* Copyright 2024 Adobe
85
* All Rights Reserved.
96
*
107
* NOTICE: All information contained herein is, and remains
@@ -24,37 +21,62 @@
2421
use Laminas\Crypt\Hmac as HMACEncryption;
2522
use Laminas\OAuth\Http\Utility as HTTPUtility;
2623

27-
class HmacSignature
24+
class Utility extends HTTPUtility
2825
{
29-
private const HMAC_ALGO = '256';
30-
3126
/**
3227
* @param array $params
28+
* @param $signatureMethod
3329
* @param string $consumerSecret
34-
* @param string|null $tokenSecret
35-
* @param string|null $method
36-
* @param string|null $url
30+
* @param null $tokenSecret
31+
* @param null $method
32+
* @param null $url
3733
* @return string
3834
*/
3935
public function sign(
4036
array $params,
41-
string $consumerSecret,
42-
?string $tokenSecret = null,
43-
?string $method = null,
44-
?string $url = null
37+
$signatureMethod,
38+
$consumerSecret,
39+
$tokenSecret = null,
40+
$method = null,
41+
$url = null
4542
): string {
4643
unset($params['oauth_signature']);
4744

4845
$binaryHash = HMACEncryption::compute(
4946
$this->assembleKey($consumerSecret, $tokenSecret),
50-
self::HMAC_ALGO,
47+
$signatureMethod,
5148
$this->getBaseSignatureString($params, $method, $url),
5249
HMACEncryption::OUTPUT_BINARY
5350
);
5451

5552
return base64_encode($binaryHash);
5653
}
5754

55+
/**
56+
* Cast to authorization header
57+
*
58+
* @param array $params
59+
* @param null $realm
60+
* @param bool $excludeCustomParams
61+
* @return string
62+
*/
63+
public function toAuthorizationHeader(array $params, $realm = null, $excludeCustomParams = true)
64+
{
65+
$headerValue = [];
66+
foreach ($params as $key => $value) {
67+
if ($excludeCustomParams) {
68+
if (! preg_match("/^oauth_/", $key)) {
69+
continue;
70+
}
71+
}
72+
$headerValue[] = $this->urlEncode($key)
73+
. '="'
74+
. $this->urlEncode($value) . '"';
75+
}
76+
77+
return implode(",", $headerValue);
78+
}
79+
5880
/**
5981
* Assemble key from consumer and token secrets
6082
*
@@ -69,7 +91,7 @@ private function assembleKey(string $consumerSecret, ?string $tokenSecret): stri
6991
$parts[] = $tokenSecret;
7092
}
7193
foreach ($parts as $key => $secret) {
72-
$parts[$key] = HTTPUtility::urlEncode($secret);
94+
$parts[$key] = self::urlEncode($secret);
7395
}
7496

7597
return implode('&', $parts);
@@ -87,21 +109,20 @@ private function getBaseSignatureString(array $params, $method = null, $url = nu
87109
{
88110
$encodedParams = [];
89111
foreach ($params as $key => $value) {
90-
$encodedParams[HTTPUtility::urlEncode($key)] =
91-
HTTPUtility::urlEncode($value);
112+
$encodedParams[self::urlEncode($key)] =
113+
self::urlEncode($value);
92114
}
93115
$baseStrings = [];
94116
if (isset($method)) {
95117
$baseStrings[] = strtoupper($method);
96118
}
97119
if (isset($url)) {
98-
// should normalise later. here is the problem
99-
$baseStrings[] = HTTPUtility::urlEncode($url);
120+
$baseStrings[] = self::urlEncode($url);
100121
}
101122
if (isset($encodedParams['oauth_signature'])) {
102123
unset($encodedParams['oauth_signature']);
103124
}
104-
$baseStrings[] = HTTPUtility::urlEncode(
125+
$baseStrings[] = self::urlEncode(
105126
$this->toByteValueOrderedQueryString($encodedParams)
106127
);
107128

lib/internal/Magento/Framework/Oauth/Oauth.php

Lines changed: 14 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@
66

77
namespace Magento\Framework\Oauth;
88

9-
use GuzzleHttp\Subscriber\Oauth\Oauth1;
10-
use Laminas\OAuth\Http\Utility;
11-
use GuzzleHttp\Psr7\Request;
12-
use Psr\Http\Message\RequestInterface;
9+
use Magento\Framework\Oauth\Helper\Utility;
1310
use Magento\Framework\Encryption\Helper\Security;
1411
use Magento\Framework\Phrase;
1512
use Magento\Framework\Oauth\Exception as AuthException;
16-
use Magento\Framework\App\RequestInterface as AppRequest;
1713

1814
/**
1915
* Authorization service.
@@ -25,11 +21,6 @@ class Oauth implements OauthInterface
2521
*/
2622
protected $_oauthHelper;
2723

28-
/**
29-
* @var Utility
30-
*/
31-
protected $_httpUtility;
32-
3324
/**
3425
* @var \Magento\Framework\Oauth\NonceGeneratorInterface
3526
*/
@@ -41,35 +32,26 @@ class Oauth implements OauthInterface
4132
protected $_tokenProvider;
4233

4334
/**
44-
* @var AppRequest
45-
*/
46-
private AppRequest $request;
47-
48-
/**
49-
* @var Oauth1|null
35+
* @var Utility
5036
*/
51-
private ?Oauth1 $oauth1Helper = null;
37+
private Utility $hmacSignatureHelper;
5238

5339
/**
5440
* @param Helper\Oauth $oauthHelper
5541
* @param NonceGeneratorInterface $nonceGenerator
5642
* @param TokenProviderInterface $tokenProvider
57-
* @param AppRequest $request
58-
* @param Utility|null $httpUtility
43+
* @param Utility $utility
5944
*/
6045
public function __construct(
6146
Helper\Oauth $oauthHelper,
6247
NonceGeneratorInterface $nonceGenerator,
6348
TokenProviderInterface $tokenProvider,
64-
AppRequest $request,
65-
Utility $httpUtility = null
49+
Utility $utility
6650
) {
6751
$this->_oauthHelper = $oauthHelper;
6852
$this->_nonceGenerator = $nonceGenerator;
6953
$this->_tokenProvider = $tokenProvider;
70-
$this->request = $request;
71-
// null default to prevent ObjectManagerFactory from injecting, see MAGETWO-30809
72-
$this->_httpUtility = $httpUtility ?: new Utility();
54+
$this->hmacSignatureHelper = $utility;
7355
}
7456

7557
/**
@@ -172,18 +154,16 @@ public function buildAuthorizationHeader(
172154
'oauth_version' => '1.0',
173155
];
174156
$headerParameters = array_merge($headerParameters, $params);
175-
$headerParameters['oauth_signature'] = $this->_httpUtility->sign(
157+
$headerParameters['oauth_signature'] = $this->hmacSignatureHelper->sign(
176158
$params,
177-
$signatureMethod,
159+
'SHA256',
178160
$headerParameters['oauth_consumer_secret'],
179161
$headerParameters['oauth_token_secret'],
180162
$httpMethod,
181163
$requestUrl
182164
);
183-
$authorizationHeader = $this->_httpUtility->toAuthorizationHeader($headerParameters);
184-
// toAuthorizationHeader adds an optional realm="" which is not required for now.
185-
// http://tools.ietf.org/html/rfc2617#section-1.2
186-
return str_replace('realm="",', '', $authorizationHeader);
165+
166+
return $this->hmacSignatureHelper->toAuthorizationHeader($headerParameters);
187167
}
188168

189169
/**
@@ -208,35 +188,16 @@ protected function _validateSignature($params, $consumerSecret, $httpMethod, $re
208188
);
209189
}
210190

211-
$allowedSignParams = $params;
212-
unset($allowedSignParams['oauth_signature']);
213-
214-
$calculatedSign = $this->_httpUtility->sign(
215-
$allowedSignParams,
216-
$params['oauth_signature_method'],
191+
$calculatedSign = $this->hmacSignatureHelper->sign(
192+
$params,
193+
'SHA256',
217194
$consumerSecret,
218195
$tokenSecret,
219196
$httpMethod,
220197
$requestUrl
221198
);
222199

223-
$calculatedSign2 = $this->getOauthHelper(
224-
[
225-
'consumer_key' => $params['oauth_consumer_key'],
226-
'consumer_secret' => $consumerSecret,
227-
'token' => $params['oauth_token'],
228-
'token_secret' => $tokenSecret
229-
]
230-
)->getSignature($this->getRequestFromArray(
231-
[
232-
'method' => $httpMethod,
233-
'uri' => $requestUrl,
234-
'headers' => $this->request->getHeaders()->toArray(),
235-
'body' => $httpMethod == 'GET' ? null : json_encode($this->request->getParams()) //this does not cover all cases request type
236-
]
237-
), $params);
238-
239-
if (!Security::compareStrings($calculatedSign2, $params['oauth_signature'])) {
200+
if (!Security::compareStrings($calculatedSign, $params['oauth_signature'])) {
240201
throw new AuthException(new Phrase('The signature is invalid. Verify and try again.'));
241202
}
242203
}
@@ -328,31 +289,4 @@ protected function _checkRequiredParams($protocolParams, $requiredParams)
328289
throw $exception;
329290
}
330291
}
331-
332-
/**
333-
* @param array $params
334-
* @return Oauth1
335-
*/
336-
private function getOauthHelper(array $params): Oauth1
337-
{
338-
if (!$this->oauth1Helper) {
339-
$this->oauth1Helper = new Oauth1($params);
340-
}
341-
342-
return $this->oauth1Helper;
343-
}
344-
345-
/**
346-
* @param array $data
347-
* @return RequestInterface
348-
*/
349-
private function getRequestFromArray(array $data): RequestInterface
350-
{
351-
$method = $data['method'] ?? 'GET';
352-
$uri = $data['uri'] ?? '';
353-
$headers = $data['headers'] ?? [];
354-
$body = $data['body'] ?? '';
355-
356-
return new Request($method, $uri, $headers, $body);
357-
}
358292
}

0 commit comments

Comments
 (0)