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

Denied when swapping SPAPI Auth Code for Refresh/Access Token #739

Closed
alex-lehan-bloom opened this issue Oct 28, 2020 · 30 comments
Closed

Comments

@alex-lehan-bloom
Copy link

I'm new to SPAPI and have been able to get most things working. I am even able to redirect the user from our app to Amazon Seller Central to confirm our app's access to that user's Amazon Seller account. When the user confirms, Amazon Seller Central redirects back to our app with the spapi_oauth_code in the redirect URL, just like the docs say.

Everything is working fine up until this point. But then, when I try to use the spapi_oauth_code to get a refresh / access token from Login with Amazon, my request always fails with an "invalid grant type" error, even though my grant type is "authorization_code", just like the doc says. I've read issue #699 and issue #713 , but I don't think my configuration is the issue. At least, I've checked the configuration against the documentation several times.

Here's what I've done so far. Am I doing something wrong?

My IAM Policy JSON, which is attached to my IAM Role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:*:*:*"
        }
    ]
}

My IAM Role is attached to my IAM User, along with STS. In the code below, I replaced my IAM Role ID with 0s.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::000000000:role/SellingPartnerAPIRole"
        }
    ]
}

Up to now everything seems okay. I'm doing the Website authorization. And the user is able to give us consent to their Amazon Seller Account. On the redirect, I get back this:

https://test.com/accounts?&spapi_oauth_code=ANLTDkLEBxVfIePEaFxV&state=b221583e-373c-4104-9176-c6279adc5aa5&selling_partner_id=45554445445

Again, all seems okay. Now here is where the issue is. I do the request to swap the auth code above for an access token. The docs say to use query parameters so that's what I did.

    const test = await fetch(
      `https://api.amazon.com/auth/o2/token?code=${spapiCode}&client_id=${clientId}&client_secret=${secret}&grant_type=authorization_code&redirect_uri=https://test.com/accounts`,
     {
        method: "post",
      headers: {
       "Content-Type": "application/x-www-form-urlencoded",
      },
    }
    );

According to the docs, this is okay. If I remove one of the parameters I get the excepted response, such as "code missing" or "client_id missing". But if I leave all the query parameters, I actually get a 500 back from the server.

If I change the query parameters to req body parameters, then I get back the:

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


@charliecode
Copy link

charliecode commented Oct 28, 2020

@alex-lehan-bloom When you redirect the user to Seller Central what does your URL look like, are you using the version=beta param on it?

@alex-lehan-bloom
Copy link
Author

alex-lehan-bloom commented Oct 28, 2020

Wow, @charliecode , you're amazing. You seriously have the quickest replies.

Yeah, I do have the version=beta param on it.

Here's what I open. I just replaced the app ID with 0s. Does anything look wrong with this?

 window.open(
              `https://sellercentral.amazon.com/apps/authorize/consent?application_id=amzn1.sellerapps.app.000000000000000&state=none&version=beta`
            );

@rogersv
Copy link

rogersv commented Oct 28, 2020

Hi, did you use a real redirect url? It is possible that amazon gets an internal error if the url is invalid or not using https.

@charliecode
Copy link

@alex-lehan-bloom What I'm thinking is this. Because you have the version=beta in the url, this means this is not a production auth call but rather a test auth call. Therefore the spapi_oauth_code returned back to you, is a dummy. So when you're trying to get the refresh token so you can get your actual access token the system sees your dummy spapi_oauth_code and doesn't allow it to go through. Everything in the LWA request looks similar to what I did. I don't have time to test this out right now but I will later today. I could be wrong on this, it's just a theory until I test it. I did this like 2 weeks ago so I honestly don't remember if my LWA request went through with the dummy spapi_oauth_code.

I also went straight to getting the auth working. But then I realized it was better to get the test auth flow working first and then move on to a Self Authorization so I could start working on the API. The reason for this is because you cannot remove the version=beta until your app is published and approved by Amazon. You can read about that in issue #726. I'll test later and let you know unless I see you get if figured out before then.

@alex-lehan-bloom
Copy link
Author

@rogersv , good question. I did use a real redirect URL I believe, at least I'm using the same one that I have in my Amazon Seller Central application. I think it must be ok because it redirects back to my app using that URL after the user gives consent to our app in their Amazon Seller Central account.

@charliecode , thank you! That would be amazing if that is the issue. Then I could move on to making SPAPI calls and use Self Authorization until I actually publish my app.

@charliecode
Copy link

charliecode commented Oct 28, 2020

@alex-lehan-bloom So I just made the request to test it with the dummy spapi_oauth_code. The error I got is below. Again, there could be something wrong with my request, although I do not think so. I have not tested this a ton and this is just a theory but in the event yours looks similar maybe I am right about the dummy code being the issue. Would be nice if someone from Amazon would chime in to verify because the docs only mention the test auth flow working from the seller central side. They do not mention whether the flow will continue to work when sending the dummy spapi_oauth_code to LWA to get the refresh and access tokens. And you can't really say your entire test auth flow is finished and tested until you can verify you've been given a dummy refresh and access token from LWA.

{ "error_description": "The request has an invalid grant parameter : code", "error": "invalid_grant" }

UPDATE: SEE COMMENT BELOW

@alex-lehan-bloom
Copy link
Author

@charliecode , that's exactly the same issue I hit. Thank you! I'll working on getting my app published and approved by Amazon so I can confirm.

@alex-lehan-bloom
Copy link
Author

Closing for now.

@petergzli
Copy link

Hey @charliecode @alex-lehan-bloom any developments with this? I just started and have reached this step and unable to proceed {
"error_description": "The request has an invalid grant parameter : code",
"error": "invalid_grant"
}

Am I stuck testing on self-grant option only?

@alex-lehan-bloom
Copy link
Author

@petergzli , it looks like it. That's the same error I got.

@charliecode
Copy link

charliecode commented Nov 12, 2020

Hello @petergzli. I believe so. I do believe the issue is with the "dummy code" as mentioned above. Nobody has chimed in from Amazon yet, so until they do we won't 100% know. But, I'd say what we came up with is probably correct. Would definitely be nice if Amazon could add more to the documentation on this. And as I said before, it seems being able to do the entire flow, including using the spapi_oauth_code to get dummy LWA data would be a nice addition to ensure our entire flow is working correctly. Until then I would recommend doing the self authorization. Not sure if you read #726 yet or not, but it helps bring this all together.

UPDATE: SEE COMMENT BELOW

@charliecode
Copy link

To take it a step further it would also be nice to then use that dummy LWA access and refresh tokens to at least be able to make sandbox requests. Then you would be ensured that your entire oauth flow works from beginning to end.

@petergzli
Copy link

@charliecode I agree it would be incredibly helpful for development else anything can go wrong once we submit for review and they try out the same flow in production servers...

Btw you are fantastic, thank you for your constant contribution to all these threads. You are truly appreciated.

@charliecode
Copy link

UPDATE ON PREVIOUS COMMENTS:

When trying to swap the spapi_oauth_code via LWA's https://api.amazon.com/auth/o2/token endpoint, you should be able to successfully receive the response Amazon mentions in their documentation even if your spapi_oauth_code came from a test (draft state) request. Namely the access_token, token_type, expires_in and refresh_token. Previously some of us were getting errors when attempting to do this. This is not currently the case. So, if you're currently getting errors when trying to do this, it's more than likely an issue with your request.

@Khungersumit
Copy link

Hello Everyone
So after reading the entire chat above I have another question while working with SP-API. Can anyone please have a look, I would be really thankful to you :)

After exchanging the aut_code with the LWA refresh token, I got the following things
access_token | refresh_token | token_type | expires_in

Then
I tried to call (ref : here)

https://sellingpartnerapi-na.amazon.com/orders/v0/orders with headers
x-amz-access-token : got in the previous step
x-amz-date and user-agent

Now when I HIT the request I get the following response
"message": "Access to requested resource is denied.",
"code": "MissingAuthenticationToken"

Is there anything I am doing wrong?
Please share your thoughts
Thanks in advance to all 😊

@EddieLongStockings
Copy link

Hi same problem. Using Self Authorization as app is still in draft status:
https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md#self-authorization

@mehmetuygun
Copy link

Hello Everyone
So after reading the entire chat above I have another question while working with SP-API. Can anyone please have a look, I would be really thankful to you :)

After exchanging the aut_code with the LWA refresh token, I got the following things
access_token | refresh_token | token_type | expires_in

Then
I tried to call (ref : here)

https://sellingpartnerapi-na.amazon.com/orders/v0/orders with headers
x-amz-access-token : got in the previous step
x-amz-date and user-agent

Now when I HIT the request I get the following response
"message": "Access to requested resource is denied.",
"code": "MissingAuthenticationToken"

Is there anything I am doing wrong?
Please share your thoughts
Thanks in advance to all 😊

Did you find any solution for this :/?

@ezpinsky
Copy link

UPDATE ON PREVIOUS COMMENTS:

When trying to swap the spapi_oauth_code via LWA's https://api.amazon.com/auth/o2/token endpoint, you should be able to successfully receive the response Amazon mentions in their documentation even if your spapi_oauth_code came from a test (draft state) request. Namely the access_token, token_type, expires_in, and refresh_token. Previously some of us were getting errors when attempting to do this. This is not currently the case. So, if you're currently getting errors when trying to do this, it's more than likely an issue with your request.

It seems that this is not correct because amazon differentiates between private (unlisted/draft) and public (listed) in the docs here https://github.com/amzn/selling-partner-api-models/issues/739 with regard to authorization workflow. It is implied that the only time you can use the OAuth workflow is for a Public application (i.e. listed on the AppStore). SelfAuthorization is the only way to use a Private (unlisted) application. This seems to be the reason that everyone is getting the 500 error with a correct request.

@yuri-lonesomelabs
Copy link

yuri-lonesomelabs commented Jun 11, 2021

I'm getting 500 when trying to get a refresh token on a draft app.

Can anyone share a request structure that actually worked when trying to exchange spapi_oauth_code for a refresh token on a drafted app? Or at least confirm that it's possible/not possible.

If not possible, how are you guys testing the flow before going public?

EDIT: Getting these headers with the 500 error:
{'Server': 'Server', 'Date': 'Fri, 11 Jun 2021 08:31:49 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '2', 'Connection': 'keep-alive', 'x-amz-rid': '5T2RS7ZNSSS8ME94NRA3', 'x-amzn-RequestId': '81715f72-669b-4801-882e-c281d0ccaed4', 'X-Amz-Date': 'Fri, 11 Jun 2021 08:31:49 GMT', 'x-amzn-ErrorType': 'InternalFailure:http://internal.amazon.com/coral/com.amazon.coral.service/', 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Vary': 'Content-Type,Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent', 'Permissions-Policy': 'interest-cohort=()'}

@ezpinsky
Copy link

ezpinsky commented Jun 11, 2021

@yuri-lonesomelabs It is not possible and that fact is barely implied by the awful documentation. See my earlier comment below, but in short you will have to apply for the app to be listed and get approved for you to test this request. Your app does not have to be complete for you to apply. May as well apply now because it can take some time (around 4 business days) to get approved and then they take another 10 business days to translate your app listing info before it gets listed.
Oh and don't forget to remove the version=beta from the OAuth link when you do finally get listed.

See my comment below correcting my this incorrect comment

It seems that this is not correct because amazon differentiates between private (unlisted/draft) and public (listed) in the docs here https://github.com/amzn/selling-partner-api-models/issues/739 with regard to authorization workflow. It is implied that the only time you can use the OAuth workflow is for a Public application (i.e. listed on the AppStore). SelfAuthorization is the only way to use a Private (unlisted) application. This seems to be the reason that everyone is getting a 500 error. Of course... amazon has terrible error handling with barely any info.

@yuri-lonesomelabs
Copy link

@ezpinsky so you just have an unfinished app published on the marketplace? Is there no other way to test the app before that, at least the APIs with some sort of dummy data?

@ezpinsky
Copy link

ezpinsky commented Jun 13, 2021

@ezpinsky so you just have an unfinished app published on the marketplace? Is there no other way to test the app before that, at least the APIs with some sort of dummy data?

Yup, we have an incomplete app that is published to the marketplace. You can put the price of the app as "Contact seller for pricing" so that no one can try your app without first contacting you.

You can test all the APIs with Self Authorization. The only thing you can't test until listed is swapping the SP-API auth code for refresh token. Pretty annoying that you cant really test it until listed but in some ways it makes sense. They only want you to be able to authorize sellers to your app if they have approved it and made sure it's not harmful to sellers I guess. I hope this helps.

The above is wrong.

@ezpinsky
Copy link

ezpinsky commented Jun 28, 2021

@yuri-lonesomelabs
Turns out we weren't making the request correctly. It does work in draft mode. Our mistake was twofold.

  1. We were putting all the parameters for the request as a query on the url, because that's what the docs say to do...

The call must include the following query parameters...

A query parameter by definition goes on the end of the url... But of course this is wrong because the docs are terrible. You have to put the client_id, client_secret, code, and grant_type into the body of your request.

  1. Didn't realize that the the LWA exchange is actually a grantless operation and doesn't need to be signed or anything. It doesn't say this anywhere in the docs that I could find though. It does mention getAuthorizationCode is a grantless operation but not sure what that is and it is not clear if that refers to the LWA Exhange.

@SouravPal95
Copy link

@ezpinsky Thank you so much for that solution. Documentations need to be more robust. Till then the community is all we got.
🧠🧠

@xbaha
Copy link

xbaha commented Jul 17, 2021

Why there is a return URL? if the reply is Json???

@agptaa
Copy link

agptaa commented Nov 15, 2021

Hi
I am facing 401 issue while making a post request for a refresh token. I am sending following as the request body -
{
"grant_type": "authorization_code",
"code": spapi_oauth_code_fromURL, // auth code coming from the URL params
"redirect_uri": ,
"client_id": process.env.CLIENT_ID, // from LWA credentials
"client_secret": process.env.CLIENT_SECRET, // from LWA credentials
}
Can anyone suggest what might be wrong ?

@jilliansd
Copy link

Hi,

I am facing a 400 error when trying to make a post request to get a refresh token from the sp_oauth token:=, am sending this via postman:

var axios = require('axios');
var qs = require('qs');
var data = qs.stringify({
'grant_type': 'authorization_code',
'code': 'ANnGBdMPnXAlrMyfUdwU',
'client_id': 'amzn1.application-oa2-client.cf71c857f2fd4f2c9688516xxxxxxx',
'client_secret': 'bba375434456e9917fcd5539c4324cc0e3182cccb9f1694ce3c63beexxxxxxx',
'redirect_uri': 'https://dashboard.aaa.com/api/amzn/redirect'
});

var config = {
method: 'post',
url: 'https://api.amazon.com/auth/o2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
data : data
};

axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

I am getting back: 400 Bad request:

{
"error_index": "nk74kjk1VvJt-2-6787LegAAAAAAAAABQQnHaBVBp4XYo69U3I-OIQGvRBEbNoklBlrU5y0PNK7xvv16-uq0Zs2BAGrJ-mt4ugp4Ic9jkShoBmEHb-iFKGpkuzBrhJ3_CiqKzbAQn2OK7-zCciNGAOUZHqZTmVXtjLjfsZl1s0m4US8dqE8-QcNkOMua-S-23E4wnldXOcJrDCcCrPMZZk5GM6BKLDKoeS2ZEVj7sLQg1FjpzAa7rQ==",
"error_description": "Malformed request",
"error": "invalid_request"
}

Anyone had success exchanging sp_oauth code for a refresh token? Please share any pointers on how to fix this problem. The request format seems to be a problem but I could not figure it out.

@sofian-ysf
Copy link

Really helpful feed, I'm using React JS and am getting stuck on the step just prior to this (retrieving the spapi_oauth_code from the url). The workflow authorises correctly and the query parameters show instantaneously then it redirects back to my webpage. The parameters are available when I check the chrome console network tab. How am I supposed to retrieve this to use in the following post request?

@albinsopaj
Copy link

albinsopaj commented Sep 21, 2023

Really helpful feed, I'm using React JS and am getting stuck on the step just prior to this (retrieving the spapi_oauth_code from the url). The workflow authorises correctly and the query parameters show instantaneously then it redirects back to my webpage. The parameters are available when I check the chrome console network tab. How am I supposed to retrieve this to use in the following post request?

Hey. Did you find out how to extract (parse, decode) the spapi_oauth_code from the URL? I'm stuck at this, and I'd really appreciate some help.

[*** SOLVED ***]

@albinsopaj
Copy link

into the body of your request

Yep. The solution that you proposed worked for me. I created the following array.

$data = [
      'grant_type' => 'authorization_code',
      'code' => '*******************************************',
      'redirect_uri' => '*******************************************',
      'client_id' => '************************************************',
      'client_secret' => '***********************************************'
];

I sent it via a POST request, and as a response I got back the following:

{
    "access_token": "*************************************",
    "refresh_token": "*****************************************",
    "token_type": "bearer",
    "expires_in": 3600
}

All seems to be working correctly.

@shreeharsh-a shreeharsh-a transferred this issue from amzn/selling-partner-api-docs May 24, 2024
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