Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aws Sign4 wrong calcualation #113

Closed
dipakb1 opened this issue Jun 4, 2020 · 17 comments
Closed

Aws Sign4 wrong calcualation #113

dipakb1 opened this issue Jun 4, 2020 · 17 comments

Comments

@dipakb1
Copy link

dipakb1 commented Jun 4, 2020

I am using API method "b) Directly making calls to Selling partner APIs".

I followed all the steps correctly:

Step 1. Request a Login with Amazon access token
--> This API is working successfully & Getting access token.

Step 2. Construct a Selling Partner API URI

After that, I took access_token and pass into options header request- x-amz-access-token.
Step 3. Add headers to the URI
Step 4. Create and sign your request
After completing 4 steps, my code are as follows:

let options = {
    service: 'execute-api',
    region:'eu-west-1',
    method: 'GET',
    url: 'https://sellingpartnerapi-eu.amazon.com/vendor/orders/v1/purchaseOrders/?includeDetails=true&createdBefore=2020-04-20T14:00:00-08:00&createdAfter=2020-04-14T00:00:00-08:00',
    headers: {
      'Content-Type': 'application/json',
      'host':'sellingpartnerapi-eu.amazon.com',
      'x-amz-access-token':access_token,
      'x-amz-date': '20200604T061745Z',
      'user-agent':'My App(Language=Node.js;Platform=Windows/10)'
    }
  }

let signedRequest = aws4.sign(options,
{
  secretAccessKey: secretAccessKey,
  accessKeyId: accessKeyId,
})
      
console.dir("signedRequest");
console.dir(signedRequest);

delete signedRequest.headers['Host']
delete signedRequest.headers['Content-Length']
      
request(awsres, function(err, res, body) {
    console.dir("err");
    console.dir(err);
    console.dir("res");
    console.dir(res.body);
});

But, After calling API 'https://sellingpartnerapi-eu.amazon.com/vendor/orders/v1/purchaseOrders'.
I am getting a sign response with error-
'The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method.'

Please suggest for how to calculate correct was4 signature in details.

@dipakb1 dipakb1 changed the title Aws Sign wrong calcualation Aws Sign4 wrong calcualation Jun 4, 2020
@mhart
Copy link
Owner

mhart commented Jun 4, 2020 via email

@dipakb1
Copy link
Author

dipakb1 commented Jun 4, 2020

I have already added a code-snippet. Do you think I have missed anything?

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Why is the service execute-api? Is that what the Amazon documentation says to use?

Also, please see https://github.com/mhart/aws4#aws4signrequestoptions-credentials for what options you can use to sign (url is not one of them)

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Also, are you doing this in the browser? If so, you might find https://github.com/mhart/aws4fetch easier to use

@dipakb1
Copy link
Author

dipakb1 commented Jun 4, 2020

Why is the service execute-api? Is that what the Amazon documentation says to use?

Also, please see https://github.com/mhart/aws4#aws4signrequestoptions-credentials for what options you can use to sign (url is not one of them)

Why is the service execute-api? Is that what the Amazon documentation says to use?

Also, please see https://github.com/mhart/aws4#aws4signrequestoptions-credentials for what options you can use to sign (url is not one of them)

Okay. I will make changes and let you know.

@dipakb1
Copy link
Author

dipakb1 commented Jun 4, 2020

Why is the service execute-api? Is that what the Amazon documentation says to use?

Also, please see https://github.com/mhart/aws4#aws4signrequestoptions-credentials for what options you can use to sign (url is not one of them)

I am using Selling partner API-
when I am using the following code-

var opts = { host: 'sellingpartnerapi-eu.amazon.com', path: '/vendor/orders/v1/purchaseOrders', service: 'execute-api', region: 'eu-west-1'}
        let awsres= aws4.sign(opts, { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey })
        console.log("aws res");
        console.log(awsres);

          request(awsres, function(err, res, body) {
              console.dir("err");
              console.dir(err);
              console.dir("res");
              console.dir(res.body);
          });

getting error -
Error: options.uri is a required argument.
that's why I have passed Url parameter in option.

If I passed url: 'https://sellingpartnerapi-eu.amazon.com/vendor/orders/v1/purchaseOrders?includeDetails=true&createdBefore=2020-04-20T14:00:00-08:00&createdAfter=2020-04-14T00:00:00-08:00'
I am not getting a response error- '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.'

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

This library is for signing requests using the Node.js http request method – as documented here: https://nodejs.org/docs/latest-v12.x/api/http.html#http_http_request_options_callback (the http.request(options[, callback]) version)

That error is not coming from this library (aws4) and nor is it coming from Node.js http request method – you must be using some external library.

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

You can see an example of how to make requests with Node.js in the README: https://github.com/mhart/aws4#example

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Also if you provide a link to the service documentation that says you should be using this method, I might be able to help

@dipakb1
Copy link
Author

dipakb1 commented Jun 4, 2020

Also if you provide a link to the service documentation that says you should be using this method, I might be able to help

I am sharing with you, documentation which I have used to calculate the sign.
https://prnt.sc/stum9a
https://prnt.sc/stumyz
https://prnt.sc/stunej
https://prnt.sc/stunt7
https://prnt.sc/stuod4
https://prnt.sc/stuor3

@dipakb1
Copy link
Author

dipakb1 commented Jun 4, 2020

You can see an example of how to make requests with Node.js in the README: https://github.com/mhart/aws4#example

I have previously referred this link and also make some changes as per PDF which is given by Amazon.

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

So it says there that the region has to be us-east-1.

So you probably want to do something like this:

let options = {
  service: 'execute-api',
  region: 'us-east-1',
  host: 'sellingpartnerapi-eu.amazon.com',
  path: '/vendor/orders/v1/purchaseOrders',
  headers: {
    'X-Amz-Access-Token': access_token,
    'User-Agent': 'My App(Language=Node.js;Platform=Windows/10)'
  }
}

let signedRequest = aws4.sign(options, {
  secretAccessKey: secretAccessKey,
  accessKeyId: accessKeyId,
})

// I'm assuming your external library needs this:
signedRequest.url = 'https://' + signedRequest.host + signedRequest.path

request(signedRequest, console.dir)

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Don't put X-Amz-Date or Host headers in there – aws4 will add them for you

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Also, you can make the headers lowercase if you prefer – it shouldn't matter, but just in case it does...

  headers: {
    'x-amz-access-token': access_token,
    'user-agent': 'My App(Language=Node.js;Platform=Windows/10)'
  }

@mhart
Copy link
Owner

mhart commented Jun 4, 2020

Actually you shouldn't have a Content-Type header in there because you're making a GET request

@dipakb1
Copy link
Author

dipakb1 commented Jun 5, 2020

Thank you so much @mhart
I am getting an API response successfully, because of your code.
I have also done a few changes to it.
Here I am giving my code are as follows:

           var access_token = data.access_token;
            var endpoint = "sellingpartnerapi-eu.amazon.com";
            var path = "/vendor/orders/v1/purchaseOrders";
            var queryString ="?includeDetails=true&createdBefore=2020-05-20T14:00:00-08:00&createdAfter=2020-05-14T00:00:00-08:00";
            let options = {
              service: 'execute-api',
              region: 'eu-west-1',
              host: endpoint,
              path: path+queryString,
              headers: {
                'x-amz-access-token': access_token,
              }
            }
            
            let signedRequest = aws4.sign(options, {
              secretAccessKey: secretAccessKey,
              accessKeyId: accessKeyId,
            })

            signedRequest.url = 'https://' + signedRequest.host + signedRequest.path
 
            request(signedRequest, function(err, res, body) {
                // console.dir("err");
                // console.dir(err);
                console.dir("res");
                console.dir(res.body);
            });

Thank you so much once again.

@mhart
Copy link
Owner

mhart commented Jun 5, 2020

Glad you got it to work 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants