Skip to content
Advertisement

Having Trouble in Generating Amazon AWS Signature With PHP

I was trying to make a HTTP POST Request to amazon’s AGCOD Service API , I followed all the steps to make a signature and all the hashed keys matched the instructions here, but I still got a “The security token included in the request is invalid.” ERROR.

<?php
define('PARTNER_ID','Test');
define('ACCESS_KEY','fake-aws-key');
define('SECRET_KEY','fake-secret-key');
define('TIME_STAMP_ISO_8601',date('YmdTHisO'));
//define('TIME_STAMP_ISO_8601','20140205T171524Z');
//define('TIME_STAMP','20140205');
define('TIME_STAMP',date('Ymd'));
define('REGION_CODE','us-east-1');
define('SERVICE_NAME','AGCODService');


$secretKey = 'AWS4'.SECRET_KEY;

$hashedDateKey = hash_hmac('sha256', TIME_STAMP, $secretKey, true);//41b8dd5e0d1716ba90401d46b58b12d500accdd2ea9c2b22a2d275946c9d978e

$hashedRegionKey = hash_hmac('sha256', REGION_CODE, $hashedDateKey, true);//7b47360ce7afbe1b839e0b0e55834df99979a5414bc7f846b17c9374d230d45d

$hashedServiceKey = hash_hmac('sha256', SERVICE_NAME , $hashedRegionKey, true);//68136b0a64b2d01c8934370288b46500243645e468f521503e0d1fa73526d409

$signingKey = hash_hmac('sha256', 'aws4_request', $hashedServiceKey,true);//27cb9f5b991c2933f5faae716e99bd50c66a45811b1424128269312bdd570dff

$payload = "<CreateGiftCardRequest><creationRequestId>Test001</creationRequestId><partnerId>Test</partnerId><value><currencyCode>USD</currencyCode><amount>10</amount></value></CreateGiftCardRequest>";

$hashedPayload = hash('sha256',$payload);//50bf24a091a7463bb4a2661f93a7299c94774bc81f9fddf02af2925922b869dc

$CanonicalRequestStr = "POSTn/CreateGiftCardnnaccept:charset=UTF-8ncontent-type:charset=UTF-8nhost:agcod-v2-gamma.amazon.comnx-amz-date:".TIME_STAMP_ISO_8601."nx-amz-target:com.amazonaws.agcod.AGCODService.CreateGiftCardnnaccept;content-type;host;x-amz-date;x-amz-targetn".$hashedPayload;

$hashedCanonicalRequest = hash('sha256',$CanonicalRequestStr);//7d9f2765e4f23e85d3dce4ae264dac4f784c152f3746aff45ac7f3afd7fad649

$str2Sign = "AWS4-HMAC-SHA256n".TIME_STAMP_ISO_8601."n".TIME_STAMP."/".REGION_CODE."/".SERVICE_NAME."/aws4_requestn".$hashedCanonicalRequest;

$signature = hash_hmac('sha256', $str2Sign, $signingKey);//e32110cf663ed86460621dff12bb1139afe29d015584d208df09f149fa1b69d1

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,'https://agcod-v2-gamma.amazon.com/CreateGiftCard');
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
//curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'accept:charset=UTF-8',
'content-type:charset=UTF-8',
'host:agcod-v2-gamma.amazon.com',
'x-amz-date:'.TIME_STAMP_ISO_8601,
'x-amz-target:com.amazonaws.agcod.AGCODService.CreateGiftCard',
'Authorization:AWS4-HMAC-SHA256 Credential='.ACCESS_KEY.'/'.TIME_STAMP.'/us-east-1/AGCODService/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date;x-amz-target,Signature='.$signature,
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

$return = curl_exec($ch);

$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

curl_close($ch);

var_dump($return_code);
?>

Advertisement

Answer

The AWS SDK for PHP has a SignatureV4 implementation. There is no PHP client included for AGCOD, since it is not an AWS service, but the DynamoDB service works very similarly to how AGCOD works. I was able to hack the DynamoDB client to send requests to AGCOD instead.

<?php

require 'vendor/autoload.php'; // If installed via Composer.

// Instantiate DynamoDB client, but overwrite a bunch of the settings
// to work with the AGCOD service
$client = AwsDynamoDbDynamoDbClient::factory([
    'base_url' => 'https://agcod-v2-gamma.amazon.com',
    'key' => 'AWS_ACCESS_KEY_ID',
    'secret' => 'AWS_SECRET_ACCESS_KEY',
    'region' => 'us-east-1',
    'signature' => 'v4',
    'signature.service' => 'AGCODService',
    'signature.region' => 'us-east-1',
]);

// Add wire logger for debugging
$client->addSubscriber(GuzzlePluginLogLogPlugin::getDebugPlugin());

$body = <<<JSON
{"requestId": "Awssb0327141418PM", "partnerId": "Awssb", "utcStartDate":
"2014-03-27T00:10:10Z", "utcEndDate": "2014-03-27T23:59:59Z", "pageIndex": 0,
"pageSize": 200, "showNoOps": "true"}
JSON;

try {
    // Use underlying Guzzle feature to send request,
    // to skip some of the DynamoDB-specific logic.
    $response = $client->put('GetGiftCardActivityPage', [
        'x-amz-target' => 'com.amazonaws.agcod.AGCODService.GetGiftCardActivityPage',
        'accept'       => 'application/json'
    ], $body)->send();
} catch (AwsCommonExceptionServiceResponseException $e) {
    echo $e; // This exception class has a __toString() method.
}

Note sure if this will help much, but it could be used as a starting point if you decide to cherry pick code from the AWS SDK for PHP.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement