前提・実現したいこと
AmazonのSP-APIを用いて新規注文の確認を行おうとしています。
Node.jsのaxiosを用いてAPIにリクエストを送っているのですが、
タイトルの通り403エラーが発生してしまいレスポンスを得られていません。
問題点・解決方法をご教示ください。
発生している問題・エラーメッセージ
下記はSP-APIから返ってきたエラーレスポンスです。
json
1{ errors: 2 [ { message: 'Access to requested resource is denied.', 3 code: 'Unauthorized', 4 details: '' } ] }
該当のソースコード
ID等は変更して記載しております。
require部
js
1const axios = require('axios') 2const qs = require('querystring') 3const dateformat = require('dateformat') 4const cryptoJs = require('crypto-js')
アクセストークンを取得する部分です。
js
1// AccessTokenの取得 2const auth = () => { 3 const url = 'https://api.amazon.com/auth/o2/token' 4 const headers = { 5 'Content-Type': 'application/x-www-form-urlencoded' 6 } 7 const query = { 8 grant_type: 'refresh_token', 9 refresh_token: 'Atzr|hogehoge', 10 client_id: 'LWA_client_ID', 11 client_secret: 'LWA_client_secret' 12 } 13 return axios.post(url, qs.stringify(query), { headers: headers }) 14 .catch((err) => { 15 console.log('Error!,Auth') 16 console.log(err.response.data) 17 }) 18}
この部分は成功しており、下記のレスポンスを取得できています。
json
1{ access_token: 2 'Atza|hogehoge', 3 refresh_token: 4 'Atzr|fugafuga', 5 token_type: 'bearer', 6 expires_in: 3600 }
署名キーを取得する部分です。
この部分は下記のページをもとに作成しています。
署名バージョン 4 の署名キーを取得する方法の例
を使用しています。
js
1const accessKey = 'IAM_AccessKey' 2const secretKey = 'IAM_SecretKey' 3const regionName = 'us-west-2' 4const serviceName = 'execute-api' 5 6const getSignatureKey = (key, dateStamp, region, serviceName) => { 7 const kDate = cryptoJs.HmacSHA256(dateStamp, `AWS4${key}`) 8 const kRegion = cryptoJs.HmacSHA256(region, kDate) 9 const kService = cryptoJs.HmacSHA256(serviceName, kRegion) 10 const kSigning = cryptoJs.HmacSHA256('aws4_request', kService) 11 return kSigning 12}
実際にSP-APIにリクエストを送っている部分です。
axios.get(url, { params: query, headers: headers })
の部分までは下記の公式の手順に則って署名処理及びリクエストヘッダの作成を行い、署名は成功しました。
署名バージョン 4 を使用した AWS リクエストへの署名
js
1const order = (token) => { 2 const host = 'sellingpartnerapi-fe.amazon.com' 3 const path = '/orders/v0/orders/' 4 const contentType = 'application/x-www-form-urlencoded' 5 const date = new Date() 6 const charset = 'utf-8' 7 const isoDate = dateformat(date, 'UTC:yyyymmdd"T"HHMMss"Z"') 8 const url = `https://${host}${path}` 9 const userAgent = 'axios/0.21.1' 10 const query = { 11 'CreatedAfter': '2021-07-01', 12 'MarketplaceIds': 'A1VC38T7YXB528', 13 } 14 const canonicalHeader = `content-type:${contentType}; charset=${charset}\nhost:${host}\nuser-agent:${userAgent}\nx-amz-access-token:${token}\nx-amz-date:${isoDate}\n` 15 const signedHeaders = 'content-type;host;user-agent;x-amz-access-token;x-amz-date' 16 const canonicalPayload = cryptoJs.enc.Hex.stringify(cryptoJs.SHA256('')) 17 const canonicalRequest = `GET\n${encodeURI(path)}\n${encodeURI(qs.stringify(query))}\n${canonicalHeader}\n${signedHeaders}\n${canonicalPayload}` 18 const credentialScope = `${dateformat(date, "UTC:yyyymmdd")}/${regionName}/${serviceName}/aws4_request` 19 const signatureString = `AWS4-HMAC-SHA256\n${isoDate}\n${credentialScope}\n${cryptoJs.enc.Hex.stringify(cryptoJs.SHA256(canonicalRequest))}` 20 const signatureKey = getSignatureKey(secretKey, dateformat(date, "UTC:yyyymmdd"), regionName, serviceName) 21 const signature = cryptoJs.enc.Hex.stringify(cryptoJs.HmacSHA256(signatureString, signatureKey)) 22 23 const headers = { 24 'Content-Type': `${contentType}; charset=${charset}`, 25 'Host': host, 26 'User-Agent': userAgent, 27 'x-amz-access-token': token, 28 'X-Amz-date': isoDate, 29 'Authorization': `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders},Signature=${signature}` 30 } 31 32 axios.get(url, { params: query, headers: headers }) 33 .then((res) => { 34 console.log('order Success!') 35 console.log(res) 36 }) 37 .catch((err) => { 38 console.log('Error!,Order') 39 console.log(err) 40 console.log(err.response.data) 41 }) 42} 43 44auth().then((response) => { 45 console.log('Auth Success!') 46 order(response.data.access_token) 47})
試したこと
- アプリケーションのIAM ARNをuser,roleそれぞれに設定し試しました。
下記のポリシーをアタッチしています。
これは下記のリンクを参考に行いましたが、レスポンスは変わりませんでした。
Access to requested resource is denied 403 SP-API AMAZON - C#
json
1{ 2 "Version": "2012-10-17", 3 "Statement": [ 4 { 5 "Effect": "Allow", 6 "Action": "execute-api:Invoke", 7 "Resource": "arn:aws:execute-api:*:*:*" 8 } 9 ] 10}
- ヘッダーの修正
ヘッダー設定部分を下記のように変更しました。
旧
js
1 const headers = { 2 'Content-Type': `${contentType}; charset=${charset}`, 3 'Host': host, 4 'User-Agent': userAgent, 5 'X-Amz-Access-Token': token, 6 'X-Amz-date': isoDate, 7 'Authorization': `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders},Signature=${signature}` 8 }
現
js
1 const headers = { 2 'Content-Type': `${contentType}; charset=${charset}`, 3 'Host': host, 4 'User-Agent': userAgent, 5 'x-amz-access-token': token, 6 'X-Amz-date': isoDate, 7 'Authorization': `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders},Signature=${signature}` 8 }
X-Amz-Access-Tokenをすべて小文字に変更しました。
これは下記のIssueを参考に変更しました。
Access token is missing in the request header. #292
これにより、レスポンスは下記のように変わりました。
旧
json
1{ errors: 2 [ { message: 'Access to requested resource is denied.', 3 code: 'Unauthorized', 4 details: 'Access token is missing in the request header.' } ] } 5
現
json
1{ errors: 2 [ { message: 'Access to requested resource is denied.', 3 code: 'Unauthorized', 4 details: '' } ] } 5
補足情報(FW/ツールのバージョンなど)
$ node -v v10.19.0 $ npm -v 6.14.4
あなたの回答
tips
プレビュー