Tuesday, January 16, 2018

Create signed AWS request using PHP

Here is a simple way to generate a signed request for diferent services using AWS:


/// AWS API keys
$aws_access_key_id = 'your-aws-access-key';
$aws_secret_access_key = 'your-aws-secret';

// AWS region and Host Name (Host names are different for each AWS region)
// As an example these are set to us-west-2
$aws_region = 'us-west-2';
$host_name = 'your-url.amazonaws.com';

// MIME type of file.
$content_type = 'application/x-www-form-urlencoded';

// Service name
$aws_service_name = 'execute-api';

// UTC timestamp and date
$timestamp = gmdate('Ymd\THis\Z');
$date = gmdate('Ymd');

// HTTP request headers as key & value
$request_headers = array();
$request_headers['content-type'] = $content_type;
$request_headers['x-amz-date'] = $timestamp;
$request_headers['host'] = $host_name;

// Sort it in ascending order
ksort($request_headers);

// Canonical headers
$canonical_headers = [];
foreach($request_headers as $key => $value) {
$canonical_headers[] = strtolower($key) . ":" . $value;
}
$canonical_headers = implode("\n", $canonical_headers);

// Signed headers
$signed_headers = [];
foreach($request_headers as $key => $value) {
$signed_headers[] = strtolower($key);
}
$signed_headers = implode(";", $signed_headers);


// Cannonical request 
$canonical_request = [];
$canonical_request[] = "GET";
$canonical_request[] = "/getStatus";
$canonical_request[] = "order_id=123456";
$canonical_request[] = $canonical_headers;

//This is needed do not remove
$canonical_request[] = "";

$canonical_request[] = $signed_headers;

//If there are no content then put blank.
$canonical_request[] = hash('sha256', '');

$canonical_request = implode("\n", $canonical_request);
$hashed_canonical_request = hash('sha256', $canonical_request);

// AWS Scope
$scope = [];
$scope[] = $date;
$scope[] = $aws_region;
$scope[] = $aws_service_name;
$scope[] = "aws4_request";

// String to sign
$string_to_sign = [];
$string_to_sign[] = "AWS4-HMAC-SHA256"; 
$string_to_sign[] = $timestamp; 
$string_to_sign[] = implode('/', $scope);
$string_to_sign[] = $hashed_canonical_request;
$string_to_sign = implode("\n", $string_to_sign);

// Signing key
$kSecret = 'AWS4' . $aws_secret_access_key;
$kDate = hash_hmac('sha256', $date, $kSecret, true);
$kRegion = hash_hmac('sha256', $aws_region, $kDate, true);
$kService = hash_hmac('sha256', $aws_service_name, $kRegion, true);
$kSigning = hash_hmac('sha256', 'aws4_request', $kService, true);

// Signature
$signature = hash_hmac('sha256', $string_to_sign, $kSigning);

// Authorization
$authorization = [
' Credential=' . $aws_access_key_id . '/' . implode('/', $scope),
' SignedHeaders=' . $signed_headers,
' Signature=' . $signature
];
$authorization = 'AWS4-HMAC-SHA256' . ' ' . implode( ',', $authorization);

// Curl headers
$curl_headers = [ 'authorization: ' . $authorization ];
foreach($request_headers as $key => $value) {
$curl_headers[] = $key . ": " . $value;
}

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://your-url.amazonaws.com/getStatus?order_id=123456",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_SSL_VERIFYHOST => false,
  CURLOPT_SSL_VERIFYPEER => false,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => $curl_headers
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Popular Posts