Question
[Spaces API] How to properly create Authorization header in PHP?
The Goal
Hello all, my goal is to eventually use DO Spaces to store images for my application. However, I am trying to create an API to upload a simple text document to try.
The Issue
It seems my Authorization header is failing for some reason. It seems fine to me, but an expert is out there who knows what is going on better than I do.
The API tells me to call a hex() function in the pseudo-code of the signature creation of the API docs (Screenshot Authorization Header Pseudo-code)
But as I pointed out in that screenshot, the final signature shown in the example header is clearly not hex, but a hash. So I am confused there. The API call returns XML with an AccessDenied error. (Would be great if these errors were more specific >.>)
Below is my code, and below that is the header I am sending out. I appreciate any help, thank you. The function that makes the header and signature is getAuthorizationSignature()
public function getAuthorizationSignature(
$http_method,
$path,
$queryStringParams,
$headersNoValues,
$headersWithValues,
$sha256HashOfBody
){
$canonicalRequest = "PUT\n$path\n$queryString\n$headersWithValues\n$headersNoValues\n$sha256HashOfBody";
$stringToSign = "AWS4-HMAC-SHA256"
. "\n"
. date("Y-m-d")
. "\n"
. date("Ymd") . "/" . $this->region . "/" . "s3/aws4_request"
. "\n"
. (hash("sha256", $canonicalRequest));
$dateKey = hash_hmac("sha256", "AWS4" + $this->spaces_private_key, date("Ymd"));
$dateRegionKey = hash_hmac("sha256", $dateKey, $this->region);
$dateRegionServiceKey = hash_hmac("sha256", $dateRegionKey, "s3");
$signingKey = hash_hmac("sha256", $dateRegionServiceKey, "aws4_request");
$signature = (hash_hmac("sha256", $signingKey, $stringToSign));
return $signature;
}
public function getSignedHeaderString($headers){
$tools = new tools();
$newHeaders = '';
foreach($headers as $header){
$newHeaders .= $tools->stripWhitespace(strtolower($header)) . "\n";
}
return $newHeaders;
}
public function getAuthorizationHeader($httpMethod, $path, $queryString, $headersNoValues, $headers, $sha256HashOfBody){
$headersWithValues = $this->getSignedHeaderString($headers);
sort($headersNoValues);
$headersNoValues = implode(";", $headersNoValues);
$credential = $this->spaces_access_key . "/" . date("Ymd") . "/" . $this->region . "/s3/aws4_request";
$authHeader = "Authorization: AWS4-HMAC-SHA256 Credential=$credential, SignedHeaders=$headersNoValues, Signature=" . $this->getAuthorizationSignature($httpMethod, $path, $queryString, $headersNoValues, $headersWithValues, $sha256HashOfBody);
return [$authHeader];
}
public function upload($content, $objectKey, $contentType){
// I am overriding what I originally passed to this function for testing purposes
$content = "Text file contents";
$contentType = "text/plain";
$objectKey = "text.txt";
$requestBody = $content;
$requestMethod = "PUT";
$contentLength = strlen($content);
$payloadHash = hash("sha256", $content);
$requestHeaders = array(
"Host: aamc-cdn.nyc3.digitaloceanspaces.com",
"Content-Length: $contentLength",
"x-amz-acl: public-read",
"x-amz-content-sha256: $payloadHash",
"Content-Type: $contentType",
);
$requestHeaders_NoValues = array(
"content-length", "x-amz-acl", "content-type", "x-amz-content-sha256"
);
$authHeader = $this->getAuthorizationHeader($requestMethod, "/$objectKey", "", $requestHeaders_NoValues, $requestHeaders, $payloadHash);
$finalHeader = $authHeader + $requestHeaders;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->host . "/" . $objectKey);
curl_setopt($curl, CURLOPT_HTTPHEADER, $finalHeader);
curl_setopt($curl, CURLOPT_POSTFIELDS, $content);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_VERBOSE, 1);
$response = curl_exec($curl);
print_r($finalHeader);
return $response;
}
The header I send out:
Array
(
[0] => Authorization: AWS4-HMAC-SHA256 Credential=[Access Key]/20171111/nyc3/s3/aws4_request, SignedHeaders=content-length;content-type;x-amz-acl;x-amz-content-sha256, Signature=0dff50d6f0abccf82320ce03922bbc9cd7596b681098c4d1604a0e24e350231a
[1] => Content-Length: 18
[2] => x-amz-acl: public-read
[3] => x-amz-content-sha256: b3a11fb73200f7f32322eb34639c6fb543c3bab8e0e9b161bc8f7d49b5ca7dc8
[4] => Content-Type: text/plain
)
These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.
×
Hi Everyone!
Does anyone got out of this problem? I am also getting Access Denied and unable to get the solution.