Last active
September 26, 2023 17:17
-
-
Save rickdaalhuizen90/af633d5cab085424e86f6cab34ae55d0 to your computer and use it in GitHub Desktop.
PHP OAuth client for Magento 2 REST API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice gist!
Just tried and spotted, need to change:
HMAC-SHA1
(line 12)SHA256
(line 65)