amazon spapi との統合を行いましたが、api から制限付きトークンを取得できませんでした。リクエストに署名できませんでした。署名されたリクエストが API のリクエストと一致しません。これがjsを使用した署名コードです。コードは Authorization 文を作成し、その文を Postman で試します。ポストマンの結果はこちら。
{
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'POST
/tokens/2021-03-01/restrictedDataToken
host:sandbox.sellingpartnerapi-eu.amazon.com
user-agent:PostmanRuntime/7.28.2
x-amz-access-token:Atza|*****
host;user-agent;x-amz-access-token
2328dd129c329e308cb990d33878a6d5ffd2a8c96e62d13b873dc62d5a7ff20b'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20210805T134800Z
20210805/eu-west-1/execute-api/aws4_request
c2f03a5e26f63dfae25fcf4cb1490c88fcbdcb78760d357f9234b5d46ac0f824'
",
"code": "InvalidSignature"
}
]
}
私のせいはどこですか?
signer.html
<html>
<head>
<style>
table {
width: 80%
}
input {
width: 100%;
}
textarea {
width:100%;
height: 200px;
}
</style>
</head>
<body>
<table>
<tr>
<td width="10%">Access Key Id</td>
<td>
<input type="text" id="accessKeyId" name="accessKeyId" value="AKIAZIX*******" />
</td>
</tr>
<tr>
<td>Secret Access Key</td>
<td>
<input type="text" id="secretAccessKey" name="secretAccessKey" value="3nwTlA06******" />
</td>
</tr>
<tr>
<td>Access Token</td>
<td>
<input type="text" id="token" name="token" value="" />
</td>
</tr>
<tr>
<td>Region</td>
<td>
<input type="text" id="region" name="region" value="eu-west-1" />
</td>
</tr>
<tr>
<td>Service</td>
<td>
<input type="text" id="service" name="service" value="execute-api" />
</td>
</tr>
<tr>
<td>Method</td>
<td>
<input type="text" id="method" name="method" value="POST" />
</td>
</tr>
<tr>
<td>Host</td>
<td>
<input type="text" id="host" name="host" value="sandbox.sellingpartnerapi-eu.amazon.com" />
</td>
</tr>
<tr>
<td>URI</td>
<td>
<input type="text" id="uri" name="uri" value="/tokens/2021-03-01/restrictedDataToken" />
</td>
</tr>
<tr>
<td>Query</td>
<td>
<input type="text" id="query" name="query" value="" />
</td>
</tr>
<tr>
<td>Data</td>
<td>
<input type="text" id="data" name="data" value='{"restrictedResources":[{"method":"GET","path":"/catalog/2020-12-01/items"}]}' />
</td>
</tr>
<tr>
<td>Header</td>
<td><textarea id="header"></textarea></td>
</tr>
<tr>
<td></td>
<td><button id="send">Send</button></td>
</tr>
</table>
<script src="script/crypto-js.min.js"></script>
<script src="script/sha256.min.js"></script>
<script src="script/hmac-sha256.min.js"></script>
<script src="script/enc-base64.min.js"></script>
<script src="script/bundle.js"></script>
<script type="text/javascript">
document.getElementById('send').onclick = function () {
var crd = new Credentials(
document.getElementById('accessKeyId').value,
document.getElementById('secretAccessKey').value,
document.getElementById('token').value,
document.getElementById('region').value,
document.getElementById('service').value
);
var req = new Requests(
document.getElementById('method').value,
document.getElementById('host').value,
document.getElementById('uri').value,
document.getElementById('query').value,
document.getElementById('data').value
);
var signer = new Signer(crd,req);
document.getElementById('header').value = signer.execute();
}
</script>
</body>
</html>
bundle.js
class Credentials {
constructor(accessKeyId, secretAccessKey, token, region, service) {
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.token = token;
this.region = region;
this.service = service;
}
}
class Requests {
constructor(method, host, uri, query, data) {
this.method = method;
this.host = host;
this.uri = uri;
this.query = query;
this.data = data;
}
}
class Signer {
private
date = new Date();
termStr = "aws4_request";
algo = "AWS4-HMAC-SHA256";
signedHeaders = "host;user-agent;x-amz-access-token";
userAgent = "PostmanRuntime/7.28.2";
canonicalHeaders = function () {
var a = new Array(
"host:" + this.request.host,
"user-agent:" + this.userAgent,
"x-amz-access-token:" + this.credentials.token
);
return a.join("\n");
};
canonicalRequest = function () {
var result = '';
var a = new Array(
this.request.method.toUpperCase(),
this.request.uri,
this.queryParameters(this.request.query),
this.canonicalHeaders() + "\n",
this.signedHeaders,
this.hash(this.request.data)
);
result = a.join("\n");
console.log("canonicalRequest : \n"+result);
return result;
};
credentialScope = function () {
var a = new Array(
this.amzShortDate(),
this.credentials.region,
this.credentials.service,
this.termStr
);
return a.join("/");
};
requestToSign = function () {
var result = '';
var a = new Array(
this.algo,
this.amzLongDate(),
this.credentialScope(),
this.hash(this.canonicalRequest())
);
result = a.join("\n");
console.log("requestToSign : \n"+result);
return result;
};
signature = function () {
var result = "";
result = this.hmac(
"AWS4" + this.credentials.secretAccessKey,
this.amzShortDate()
);
result = this.hmac(result, this.credentials.region);
result = this.hmac(result, this.service);
result = this.hmac(result, this.termStr);
result = this.hmac(result, this.requestToSign()).toString();
return result;
};
authorizationHeader = function () {
var a = new Array(
"Credential=" + this.credentials.accessKeyId + "/" + this.credentialScope(),
"SignedHeaders=" + this.signedHeaders,
"Signature=" + this.signature()
);
return this.algo + " " + a.join(",");
};
requestHeader = function () {
var a = new Array(
"Authorization: " + this.authorizationHeader(),
"x-amz-access-token: " + this.credentials.token,
"x-amz-date: " + this.amzLongDate()
);
return a.join("\n");
};
queryParameters = function (queryParameterObj) {
var pieces = [];
if (queryParameterObj) {
Object.keys(queryParameterObj)
.sort()
.forEach(function (k) {
return pieces.push(
k + "=" + encodeURIComponent(queryParameterObj[k])
);
});
}
return pieces.length > 0 ? pieces.join("&") : "";
};
hash = function (str) {
return CryptoJS.SHA256(str).toString();
};
hmac = function (key, data) {
return CryptoJS.HmacSHA256(data, key);
};
amzShortDate = function () {
return this.amzLongDate().substr(0, 8);
};
amzLongDate = function () {
return this.date
.toISOString()
.replace(/[:\-]|\.\d{3}/g, "")
.substr(0, 13)+'00Z';
};
public
constructor(credentials, request) {
this.credentials = credentials;
this.request = request;
}
execute = function () {
return this.requestHeader();
};
}