Skip to content

Instantly share code, notes, and snippets.

@Rud5G
Last active May 13, 2024 13:18
Show Gist options
  • Save Rud5G/1e40985863169797e1331d341648457a to your computer and use it in GitHub Desktop.
Save Rud5G/1e40985863169797e1331d341648457a to your computer and use it in GitHub Desktop.
<?php
const CONSUMER_KEY = '<placeholder>';
const CONSUMER_SECRET = '<placeholder>';
const ACCESS_TOKEN = '<placeholder>';
const ACCESS_TOKEN_SECRET = '<placeholder>';
class RequestDTO {
public function __construct(
public string $url,
public string $method = 'GET',
public ?string $body = null,
public array $headers = [],
) {}
}
class OAuthCredentialsDTO {
public function __construct(
public string $consumerKey,
public string $consumerSecret,
public string $accessToken,
public string $accessTokenSecret
) {}
}
class OAuthRequestSigner
{
public function sign(
RequestDTO $request,
OAuthCredentialsDTO $credentials
): string {
$urlParts = parse_url($request->url);
// Normalize the OAuth params for the base string
$normalizedHeaders = $request->headers;
sort($normalizedHeaders);
$oauthParams = [
'oauth_consumer_key' => $credentials->consumerKey,
'oauth_nonce' => base64_encode(random_bytes(32)),
'oauth_signature_method' => 'HMAC-SHA256',
'oauth_timestamp' => time(),
'oauth_token' => $credentials->accessToken
];
// Create the base string
$signingUrl = $urlParts['scheme'] . '://' . $urlParts['host'] . $urlParts['path'];
$paramString = $this->createParamString($urlParts['query'] ?? null, $oauthParams);
$baseString = strtoupper($request->method) . '&' . rawurlencode($signingUrl) . '&' . rawurlencode($paramString);
// Create the signature
$signatureKey = $credentials->consumerSecret . '&' . $credentials->accessTokenSecret;
$signature = base64_encode(hash_hmac('sha256', $baseString, $signatureKey, true));
return $this->createOAuthHeader($oauthParams, $signature);
}
private function createParamString(?string $query, array $oauthParams): string
{
// Create the params string
$params = array_merge([], $oauthParams);
if (!empty($query)) {
foreach (explode('&', $query) as $paramToValue) {
$paramData = explode('=', $paramToValue);
if (count($paramData) === 2) {
$params[rawurldecode($paramData[0])] = rawurldecode($paramData[1]);
}
}
}
ksort($params);
$paramString = '';
foreach ($params as $param => $value) {
$paramString .= rawurlencode($param) . '=' . rawurlencode($value) . '&';
}
return rtrim($paramString, '&');
}
private function createOAuthHeader(array $oauthParams, string $signature): string
{
$oauthHeader = "Authorization: Oauth ";
foreach ($oauthParams as $param => $value) {
$oauthHeader .= "$param=\"$value\",";
}
return $oauthHeader . "oauth_signature=\"$signature\"";
}
}
function send(RequestDTO $request): string
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request->url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request->headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->method);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request->body ?? '');
return (string)curl_exec($ch);
}
$oauthSigner = new OAuthRequestSigner();
$request = new RequestDTO(
'https://example.com/rest/V1/cmsPage',
'POST',
'{
"page": {
"identifier": "test-page",
"title": "my-page",
"content": "<h1>hello</h1>",
"active": true
}
}',
['Content-Type: application/json']
);
$request->headers[] = $oauthSigner->sign(
$request,
new OAuthCredentialsDTO(
CONSUMER_KEY,
CONSUMER_SECRET,
ACCESS_TOKEN,
ACCESS_TOKEN_SECRET
)
);
echo send($request);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment