Skip to content

Instantly share code, notes, and snippets.

@rickdaalhuizen90
Last active September 26, 2023 17:17
Show Gist options
  • Save rickdaalhuizen90/af633d5cab085424e86f6cab34ae55d0 to your computer and use it in GitHub Desktop.
Save rickdaalhuizen90/af633d5cab085424e86f6cab34ae55d0 to your computer and use it in GitHub Desktop.
PHP OAuth client for Magento 2 REST API
<?php
/*
* OAuth 1.0a client (Example) for Magento 2
*
* @see: https://oauth.net/core/1.0a
* @see: https://tools.ietf.org/html/rfc5849
*/
class Api
{
const OAUTH_VERSION = '1.0';
const OAUTH_SIGNATURE = 'HMAC-SHA1';
private $consumerKey;
private $consumerSecret;
private $accessToken;
private $accessTokenSecret;
private $token;
public function __construct()
{
$this->consumerKey = '';
$this->consumerSecret = '';
$this->accessToken = '';
$this->accessTokenSecret = '';
}
/*
* Generate a unique nonce
*
* @return string unique string
*/
private function getNonce(): string
{
return bin2hex(random_bytes(32));
}
/*
* Create a oauth_signature
*
* @param string $verb HTTP Method/Verb
* @param string $endpoint Complete url including scheme, host, path, params
* @param array $params Parameters prefixed with oauth_
* @return string oauth_signature value
*/
private function sign(string $verb, string $endpoint, array $params): string
{
ksort($params);// @see Zend_Oauth_Signature_SignatureAbstract::_toByteValueOrderedQueryString() for more accurate sorting, including array params
// define params that will be used either in Authorization header, or as url query params, excluding 'oauth_signature'
$strParams = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$baseString = sprintf('%s&%s&%s',
strtoupper($verb),// HTTP method (POST/GET/PUT/...)
rawurlencode($endpoint),// base resource url - without port & query params & anchors, @see how Zend extracts it in Zend_Oauth_Signature_SignatureAbstract::normaliseBaseSignatureUrl()
rawurlencode($strParams)
);
$key = rawurlencode($this->consumerSecret).'&'.rawurlencode($this->accessTokenSecret);
return base64_encode(hash_hmac('SHA1', $baseString, $key, true));
}
/*
* Generate Oauth token including signature
*
* @param string $verb HTTP Method/Verb
* @param string $endpoint Complete url including scheme, host, path, params
*/
private function generateToken(string $verb, string $endpoint): string
{
$params = [
'oauth_consumer_key' => $this->consumerKey,
'oauth_token' => $this->accessToken,
'oauth_timestamp' => time(),
'oauth_nonce' => $this->getNonce(),
'oauth_version' => self::OAUTH_VERSION,
'oauth_signature_method' => self::OAUTH_SIGNATURE
];
$params['oauth_signature'] = $this->sign($verb, $endpoint, $params);
return implode(',', array_map(
function ($v, $k) { return sprintf('%s="%s"', $k, $v); }, // php ^7.4 fn($v, $k) => sprintf("%s='%s'", $k, $v) SICK!!!
$params,
array_keys($params)
));
}
/*
* Send HTTP Request to Magento 2 REST API
*
* @param string $verb HTTP Method/Verb
* @param string $endpoint Complete url including scheme, host, path, params
* @param string $token Token oauth_token
* @return null|string Json response
*/
private function client(string $verb, string $endpoint, string $token): ?string
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $endpoint,
CURLOPT_CUSTOMREQUEST => $verb,
CURLOPT_HTTPHEADER => [
'Authorization: OAuth ' . $token,
'Content-Type: application/json'
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false, // WARNING: Don't use this in production!
CURLOPT_SSL_VERIFYHOST => false, // WARNING: Don't use this in production!
CURLOPT_VERBOSE => false // Set true for Debugging
]);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
/*
* Send API Request
*
* @param string $verb HTTP Method/Verb
* @param string $endpoint Complete url including scheme, host, path, params
* @return null|array response
*/
public function request(string $verb, string $endpoint): ?array
{
$token = $this->generateToken($verb, $endpoint);
try {
$response = $this->client($verb, $endpoint, $token);
if (!$response) {
throw Exception('Failed to get reponse!');
}
return json_decode($response);
} catch(\Exception $e) {
error_log($e->getMessage());
}
}
}
$api = new Api();
print_r($api->request('GET', 'https://magento2.test/rest/V1/modules')).PHP_EOL;
exit(1);
@adamzero1
Copy link

Nice gist!
Just tried and spotted, need to change:

  • signature method to: HMAC-SHA1 (line 12)
  • algorithm to SHA256 (line 65)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment