amzn / selling-partner-api-models

This repository contains OpenAPI models for developers to use when developing software to call Selling Partner APIs.
Apache License 2.0
611 stars 733 forks source link

Authorization API Asking for Authentication Token #972

Closed vikingcodes closed 3 years ago

vikingcodes commented 3 years ago

image

In SP-API document mentioned that for Generate AuthenticationToken We need

sellingPartnerId developerId mwsAuthToken

But when we passing these parameters. API throwing error.

{ "errors": [ { "message": "Access to requested resource is denied.", "code": "MissingAuthenticationToken" } ] }

But document never mentioned that.

image

torro-uk commented 3 years ago

I am receiving the exact same error. Any help would be appreciated as the guides to convert existing MWS credentials is VERY poor!

vikingcodes commented 3 years ago

@torro-uk I checked this will not work. FYI: You can't call Authorization API until you publish your app. You can't call Authorization API on draft mode.

ShivikaK commented 3 years ago

Hello @vikingcodes

Thank you for raising this issue.

The Authorization API also requires headers in the request so you need to the AWS auth info to the request as well.

And this API can only be used with a published app and not with the app in draft mode.

Let me know if that helps clarify the issue for you.

Thanks, Shivika Khare Selling Partner API Developer Support

vikingcodes commented 3 years ago

@ShivikaK We need client_id, client_secret or accesskey, SecretKey ?

torro-uk commented 3 years ago

hi @ShivikaK

I was under the impression that the Auth API was for migrating existing MWS auth codes to the new SPAPI, so signing the request seems strange, but ok, we can do that!

On the point of our app being published, how would this work for individual sellers who only want to access their own data, like we do. I don't want to publish an app on to the marketplace for other people to see. Is this were "self authorization" comes in?

Regards, Rob

ShivikaK commented 3 years ago

Hello @torro-uk

For the individual/private sellers, your application would remain in Draft stage and you would be using the self-authorization approach to authorize your application and generate a refresh token. Hope this helps answer your question.

Thanks, Shivika Khare Selling Partner API Developer Support

ShivikaK commented 3 years ago

@ShivikaK We need client_id, client_secret or accesskey, SecretKey ?

Hello @vikingcodes

Apologies for delayed response to your query, you require both client ID and client secret along with the AWS Access Key ID and Secret key. Does that help clarify your concerns?

Thanks, Shivika Khare Selling Partner API Developer Support

vikingcodes commented 3 years ago

@ShivikaK Problem due to app was in draft . Its fixed.

VasylKolomiiets commented 3 years ago

The Authorization API also requires headers in the request so you need to the AWS auth info to the request as well

Can You show this header as the example? In documentation I didn't find it ((

VasylKolomiiets commented 3 years ago

@ShivikaK Problem due to app was in draft . Its fixed.

Only draft mode was? No header?

Trimakas commented 3 years ago

And so what is the exact request we need to reach this endpoint? No where does it mention a client_id or client_secret or ClientId or Client_id or anything similar. Can an Amazon person clearly define what the query parameters are for this request?

Romerolweb commented 2 years ago

@ShivikaK Problem due to app was in draft . Its fixed. @vikingcodes Hi, I am glad to know you fixed it. May you please show the example working in postman? That would be useful.

amylessimore commented 2 years ago

I had this issue, and I'd misunderstood the LWA tokens. I'll put my findings here in case it helps anyone else.

The Authorization API call does need x-amz-access-token header with a valid LWA token.

I assumed I couldn't get an LWA because I didn't have a refresh token. In fact, you can get a grantless LWA token, if you send the grant_type=client_credentials and the scope=sellingpartnerapi::migration.

The process I use is

  1. get a security token
  2. get a grantless LWA token (with grant_type and scope instead of refresh_token)
  3. get an authorization code via the Authorization API (using the grantless LWA)
  4. exchange the authorization code for a Refresh token

The calls to the security token service and the selling partner api are signed using the AWS signature, which is detailed in the Amazon documentation.

lwheeler-salsify commented 2 years ago

@amylessimore This solution helped me! I was able to get the LWA token in step 2 using grant_type=client_credentials, but can you confirm step 3?

In step 3, I call getAuthorizationCode, providing the sellingPartnerId, developerId, and mwsAuthToken, and now with this change I'm using the LWA token generated in step 2 as the x-amz-access-token header.

I still receive a 403 Forbidden error with Access to requested resource is denied and MissingAuthenticationToken however.

I've read elsewhere that this Authorization API requires that your amazon app has been published/accepted though, so perhaps that's my problem (mine is still pending acceptance).

amylessimore commented 2 years ago

My app is already published so I didn't get that problem. If yours is still in draft, I think it returns an error.

This is my curl from postman if it helps? Though it doesn't show the AWS Signature very well, and I'm using eu west endpoint.

curl --location --request GET 'https://sellingpartnerapi-eu.amazon.com/authorization/v1/authorizationCode?sellingPartnerId=XXXX&developerId=XXXX&mwsAuthToken=XXXX' \ --header 'Accept: application/json' \ --header 'x-amz-access-token: XXXX' \ --header 'X-Amz-Security-Token: XXXX' \ --header 'X-Amz-Date: 20220506T100604Z' \ --header 'Authorization: AWS4-HMAC-SHA256 Credential=XXXX/20220506/eu-west-1/execute-api/aws4_request, SignedHeaders=accept;host;x-amz-access-token;x-amz-date;x-amz-security-token, Signature=XXXX'

chetanshind commented 2 years ago

I had this issue, and I'd misunderstood the LWA tokens. I'll put my findings here in case it helps anyone else.

The Authorization API call does need x-amz-access-token header with a valid LWA token.

I assumed I couldn't get an LWA because I didn't have a refresh token. In fact, you can get a grantless LWA token, if you send the grant_type=client_credentials and the scope=sellingpartnerapi::migration.

The process I use is

  1. get a security token
  2. get a grantless LWA token (with grant_type and scope instead of refresh_token)
  3. get an authorization code via the Authorization API (using the grantless LWA)
  4. exchange the authorization code for a Refresh token

The calls to the security token service and the selling partner api are signed using the AWS signature, which is detailed in the Amazon documentation.

@amylessimore How do you get the security token?

Thahnasad commented 2 years ago

@amylessimore Thanks for the details, I was able to get the LWA token and used that as access Token while calling to get authorization. I did sign the request while making this call. But it is still giving error and I am not sure how to get "security token" and where to use it? @lwheeler-salsify Were you able to figure this out?

lwheeler-salsify commented 2 years ago

@Thahnasad I am currently waiting for my Amazon app to be published (it has been approved, waiting for Amazon to publish it), so I can be sure that the app being in Draft mode wasn't the problem.

Thahnasad commented 2 years ago

@lwheeler-salsify I am struggling to figure out how to get the security token mentioned by @amylessimore . Were you able to get security token?

amylessimore commented 2 years ago

@Thahnasad This is how we got the security token.

In the developer documentation it says

The Selling Partner API uses the AWS Signature Version 4 Signing Process for authenticating requests. When you send HTTP requests to the Selling Partner API, you sign the requests so that Amazon can identify who sent them. You sign requests using your AWS access keys, which consists of an access key ID and a secret access key. Amazon recommends using the AWS Security Token Service (AWS STS) to request temporary AWS access keys to sign your requests. See Creating and configuring IAM policies and entities to create an IAM user (with an AWS STS policy attached) that assumes an IAM role. You then register your application using the IAM role.

So we followed the instructions from the Creating and configuring IAM policies and entities

Now we have the AWS credentials, we send a request for temporary keys to

curl --location --request GET 'https://sts.amazonaws.com/?Version=2011-06-15&Action=AssumeRole&RoleSessionName=Test&RoleArn=arn:aws:iam::XXXX:role/SellerPartnerRole&DurationSeconds=3600' \
--header 'X-Amz-Date: 20220607T114444Z' \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=XXXX/20220607/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date, Signature=XXXX'

This is the signature in postman because the curl doesn't show it clearly:

postman signature
amylessimore commented 2 years ago

Once we have the temporary keys, we use them in the signature of the get AuthorizationCode call.

Here's another screenshot from postman as it shows the signature better than curl. It has the temporary access keys and session token from the earlier call (I'm using west for my aws region and endpoint)

postman signature 2
lwheeler-salsify commented 2 years ago

@amylessimore This is very helpful!

In your second API call, GET /authorization/v1/authorizationCode, are you manually adding the x-amz-access-token header in the Headers tab? If so, is Postman automatically adding x-amz-access-token to the SignedHeaders section of the signature for you?

It appears for me it's not adding it to the signature even though the header is present.

amylessimore commented 2 years ago

@lwheeler-salsify This is the Headers tab (including hidden headers. I didn't do anything to change those.)

postman headers

and postman has added the key to the SignedHeaders in the curl

curl --location --request GET 'https://sellingpartnerapi-eu.amazon.com/authorization/v1/authorizationCode?sellingPartnerId=XXX&developerId=XXX&mwsAuthToken=XXX' \
--header 'Accept: application/json' \
--header 'x-amz-access-token: XXX' \
--header 'X-Amz-Security-Token: XXX' \
--header 'X-Amz-Date: 20220609T110123Z' \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=XXX/20220609/eu-west-1/execute-api/aws4_request, SignedHeaders=accept;host;x-amz-access-token;x-amz-date;x-amz-security-token, Signature=XXX'

I have the 'Add authorisation data to Request Headers' set in the Authorization tab.

lwheeler-salsify commented 2 years ago

Thanks very much @amylessimore for all the info you've shared in this thread, this has been helpful and I'm sure will help other developers work through this flow.

I did end up solving my problem here, but it ended up not being related to the generation of the signature headers at all. Rather it was related to the configuration of my IAM Role. My organization had set up our application with an IAM Role associated to it, which it would somehow automatically assume when interacting with AWS. I made a single change which was:

and this somehow fixed my problem. There must be some sort of difference between explicitly assuming the Role and whatever auto-Role-assuming behavior was in place before.

So my advice to anyone who is pulling their hair out thinking "I KNOW I am building these headers correctly!" would be to double check that you are actually explicitly calling the STS Assume Role operation and using the security token in the response from that. (This is assuming your Amazon application is associated to a Role ARN and not a User)

amylessimore commented 2 years ago

Great news that you managed to get it sorted. It took a few attempts (by a few people) to get our roles set up, and then link the correct one to our Amazon Developer account!

We created an STS policy and attached it to the role, following this: https://developer-docs.amazon.com/sp-api/docs/creating-and-configuring-iam-policies-and-entities

I've seen postman collections where people assume roles each time, so I think your solution has worked for others too.

ozguraltuntas commented 2 years ago

Hi @amylessimore

Thank you for your detailed explanation, could you share the Curl for

  1. (step) get a grantless LWA token (with grant_type and scope instead of refresh_token)

Thank you

amylessimore commented 2 years ago

hi @ozguraltuntas To get the grantless LWA, i used this:

curl --location --request POST 'https://api.amazon.co.uk/auth/o2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=XXX' \
--data-urlencode 'client_secret=XXXX' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=sellingpartnerapi::migration'
TitusCln commented 2 years ago

Hi @amylessimore

I have an application that I just did Hybrid, but is not yet approval, should I have to wait to get the authorizationCode?? Image

I have managed to succeed in step 1 and 2, but when I try to get the authorization code with the previous responses I get a 500 error.

Error

daapower commented 2 years ago

Hi @amylessimore

I have an application that I just did Hybrid, but is not yet approval, should I have to wait to get the authorizationCode?? Image

I have managed to succeed in step 1 and 2, but when I try to get the authorization code with the previous responses I get a 500 error.

Error

You need to wait for it to be approved AND published. But your error code doesn't seem to be that issue. You should get another error stating that the application hasn't been assigned roles or something to that effect

abdo-muhammed commented 2 years ago

I had this issue, and I'd misunderstood the LWA tokens. I'll put my findings here in case it helps anyone else.

The Authorization API call does need x-amz-access-token header with a valid LWA token.

I assumed I couldn't get an LWA because I didn't have a refresh token. In fact, you can get a grantless LWA token, if you send the grant_type=client_credentials and the scope=sellingpartnerapi::migration.

The process I use is

  1. get a security token
  2. get a grantless LWA token (with grant_type and scope instead of refresh_token)
  3. get an authorization code via the Authorization API (using the grantless LWA)
  4. exchange the authorization code for a Refresh token

The calls to the security token service and the selling partner api are signed using the AWS signature, which is detailed in the Amazon documentation.

How to get a security token from amazon ?

karg-betacode commented 2 years ago

Screenshot 2022-10-11 at 1 29 04 PM

I can't find the model / postman file that has the endpoints for LWA refresh token. To be frank, i find the documentation quite disjointed and confusing.