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

Change authentication from MWS API to SP API? #696

Closed PasswebDev closed 2 years ago

PasswebDev commented 4 years ago

I am a developer of a proprietary CMS and I am using MWS API Reports, Feeds and Orders. For integration I use the C # Client. I would like to start making the change from MWS API to SP API. In MWS API to authenticate calls I have SellerId, MWSAuthToken, AWSAccessKeyId, Secret Key. AWSAccessKeyId and Secret Key are the values indicated in MWS credentials as attached. Can I use the same values to make SP API calls and how? 2020-10-11_10-23-07

charliecode commented 4 years ago

@PasswebDev Information on how to connect to the API can be found here under "Connecting to the Selling Partner API".

PasswebDev commented 4 years ago

Ok. I am trying to use Authorization API (https://github.com/amzn/selling-partner-api-docs/blob/main/references/authorization-api/authorization.md). Calling getAuthorizationCode with SellerId, DeveloperId and Token MWS parameters should give me a token to use in SP API calls. I am using Postman but the call getAuthorizationCode

var client = new RestClient("https://sellingpartnerapi-eu.amazon.com/authorization/v1/authorizationCode?sellingPartnerId=XXXXXXXX&developerId=XXXXXXXX&mwsAuthToken=amzn.mws.XXXXXXXXXXXXXXXX");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

the response is:

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

Shouldn't I be returning the token to access the SP API calls? Thanks

cafeasp commented 4 years ago

Any request to this lame API needs an signature.

pprbhm commented 3 years ago

Hello, You can get authorization token following this -

https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md#Step-4-Your-application-exchanges-the-LWA-authorization-code-for-a-LWA-refresh-token

If you still face issues related to making calls to authorizations API, we can look at more personal level through a Support case

Thank you

nrogers805 commented 3 years ago

@PasswebDev Information on how to connect to the API can be found here under "Connecting to the Selling Partner API".

This link gives 404 Not Found

rugved1991 commented 3 years ago

Hi,

Are you still facing this issue?

The location of the Developer Guide has changed. Please use this link going forward: https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md

Thanks, Rugved Solutions Architect, SP API

ytcitsupport-jlin commented 3 years ago

@cafeasp How should I sign the getAuthorizationCode request

jhullparkseed commented 3 years ago

Well I am very confused at the moment. I have two requests, one for FEED and one for say ORDER buyerinfo. right now I can make a call to buyerinfo signing the call with LWA and I do get a token and I do get data. I am using th4e c# SDK Amazon (y'all provided) to set up access.

Did Amazon (y'all) just change how we do security after people have coded and while you say you are implementing this by Nov 30th did you already effect FEED, because I get that error calling a FEED method (Create Document), but I do NOT get it calling order information.

Given I have a single point for authentification do I now need to manage for those calls that allow for LWA access versus restricted access?

And if you provide a link to an SDK that is tied to access, can you at least update it?

xtawfnhdx commented 3 years ago

step1:get access_token

var client = new RestClient(Amazon_AuthUrl);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
//sellingpartnerapi::migration. For the Authorization API.
request.AddParameter("scope", "sellingpartnerapi::migration");
request.AddParameter("client_id", you client id);
request.AddParameter("client_secret", you client Secret);
client.Execute(request)

step2: GET LWA

new RestClient("https://sellingpartnerapi-na.amazon.com")
RestRequest request = new RestRequest("/authorization/v1/authorizationCode", Method.GET);
request.AddQueryParameter("sellingPartnerId", xxx1);
request.AddQueryParameter("developerId", xxx2);
request.AddQueryParameter("mwsAuthToken", xxx3);
request.AddHeader("x-amz-access-token", step 1 access-token);

AWSAuthenticationCredentials aws = new AWSAuthenticationCredentials()
{
    AccessKeyId = XXX,
    SecretKey = XXX,
    Region = "us-east-1"
};
AWSSigV4Signer signer = new AWSSigV4Signer(aws);
signer.Sign(request, client.BaseUrl.Host);

client.Execute(request)

step 3:Use LWA to get access-token\refresh-token

jhullparkseed commented 3 years ago

Thank you and I'll give it a try, but where did you find this for I've not seen any documentation reflecting that code. I pulled down the SDK for c# that had the LWA and AWS signing classes, is that where you refer to AmazonAuthURL? Will this cover both orders and Feeds...

I'm happy to read documentation, but I feel like I 've read all the main links for this and none of this is very clear. I'll let you know how it works.

PasswebPass commented 3 years ago

To me the second step returns error:

`

//Step1: get access_token var client = new RestClient("https://api.amazon.com/auth/o2/token"); client.Timeout = -1; IRestRequest request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("grant_type", "client_credentials"); request.AddParameter("scope", "sellingpartnerapi::migration"); request.AddParameter("client_id", LWA_App_ClientId); request.AddParameter("client_secret", LWA_App_ClientSecret); var response = client.Execute(request).Content; string token = JsonConvert.DeserializeObject(response).Access_Token;

//step2: GET LWA client = new RestClient("https://sellingpartnerapi-eu.amazon.com"); request = new RestRequest("authorization/v1/authorizationCode", Method.GET); request.AddQueryParameter("sellingPartnerId", "XXXXXXXXXXXX"); request.AddQueryParameter("developerId", "YYYYYYYYYYYY"); request.AddQueryParameter("mwsAuthToken", "amzn.XXXXXXXXXXXXXXXXXXXXXXXX"); request.AddHeader("x-amz-access-token", token);

AWSAuthenticationCredentials aws = new AWSAuthenticationCredentials() { AccessKeyId = AWSKey, SecretKey = AWSSecret, Region = "eu-west-1" }; AWSSigV4Signer signer = new AWSSigV4Signer(aws); signer.Sign(request, client.BaseUrl.Host);

response = client.Execute(request).Content;

` response Step2A = { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" } ] }

Why?

jhullparkseed commented 3 years ago

welcome to the club because though I had them already implemented (see github doc https://github.com/amzn/selling-partner-api-models/tree/7c7d355dab8c4c490880ec0e527d20b813760022/clients/sellingpartner-api-aa-csharp) and using th4e swagger models (see api client and adding:

        private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken)
        {
            var lwaAuthorizationCredentials = new LWAAuthorizationCredentials
            {
                ClientId = clientId,
                ClientSecret = clientSecret,
                Endpoint = new Uri("https://api.amazon.com/auth/o2/token"),
                RefreshToken = refreshToken,
            };

            return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest);
        }

        private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey)
        {
            AssumeRoleResponse response1 = null;
            using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1))
            {
                var req = new AssumeRoleRequest()
                {
                    RoleArn = roleARN,
                    DurationSeconds = 950, //put anything you want here
                    RoleSessionName = Guid.NewGuid().ToString()
                };

                response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result;
            }

            //auth step 3
            var awsAuthenticationCredentials = new AWSAuthenticationCredentials
            {
                AccessKeyId = response1.Credentials.AccessKeyId,
                SecretKey = response1.Credentials.SecretAccessKey,
                Region = "us-east-1"
            };

            restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken);

            return new AWSSigV4Signer(awsAuthenticationCredentials).Sign(restRequest, host);
        }

        public class SellerAPICredentials
        {
            /// <summary>
            /// todo Add values to config file
            /// </summary>
            public string BasePath = "https://sellingpartnerapi-na.amazon.com";
            public string LWA_App_ClientId = ""; //amzn...
            public string LWA_App_ClientSecret = "";
            public string RefreshToken = ""; //Atzr...
            public string AWSSecret = "";
            public string AWSKey = ";
            public string RoleARN = "arn:aws:iam::111111111111:role/SellingPartnerRole"; //arn...
        }

I could not get FEED to work and have not gotten restricedToken APIS to work either. I've sent two support casees to amazon development with no r4esponse yet. What I don't get is that the classes/calls I use to get ALL order information works, but FEED does not. i really wish someone on the development team would at least take a stab at what is going on.

xtawfnhdx commented 3 years ago

对我来说,第二步返回错误:

`

//Step1:获取access_token var client = new RestClient(" https://api.amazon.com/auth/o2/token "); 客户端.超时 = -1; IRestRequest 请求 = 新的 RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("grant_type", "client_credentials"); request.AddParameter("scope", "salespartnerapi::migration"); request.AddParameter("client_id", LWA_App_ClientId); request.AddParameter("client_secret", LWA_App_ClientSecret); var response = client.Execute(request).Content; string token = JsonConvert.DeserializeObject(response).Access_Token;

// step2: GET LWA client = new RestClient(" https://salespartnerapi-eu.amazon.com "); request = new RestRequest("authorization/v1/authorizationCode", Method.GET); request.AddQueryParameter("salesPartnerId", "XXXXXXXXXXXX"); request.AddQueryParameter("developerId", "YYYYYYYYYYYY"); request.AddQueryParameter("mwsAuthToken", "amzn.XXXXXXXXXXXXXXXXXXXXXXXXXXX"); request.AddHeader("x-amz-access-token", token);

AWSAuthenticationCredentials aws = new AWSAuthenticationCredentials() { AccessKeyId = AWSKey, SecretKey = AWSSecret, Region = "eu-west-1" }; AWSSigV4Signer 签名者 = 新的 AWSSigV4Signer(aws); signer.Sign(请求,client.BaseUrl.Host); response = client.Execute(request).Content;

` response Step2A = { "errors": [ { "message": "访问请求的资源被拒绝。", "code": "Unauthorized", "details": "" } ] }

为什么?

My app IAM configuration: arn:aws:iam::XXXX:user/XXXXX Role IAM not used

ProNotion commented 3 years ago

I was getting the same error and after a lot of back and forth and slow replies from support, it was eventually be found to be nothing to do with my implementation but lack of required roles. I want access to order data but don't want or need access to PII data but it's not possible. To make calls to many of the most useful endpoints you have to pass checks for PII data security which are extensive and required in order to be granted the restricted roles detailed here .

PasswebPass commented 3 years ago
           If I use the jhullparkseed methods I get a different result:

            ```
             //Step1: get access_token
            var client = new RestClient("https://api.amazon.com/auth/o2/token");
            client.Timeout = -1;
            IRestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddParameter("grant_type", "client_credentials");
            request.AddParameter("scope", "sellingpartnerapi::migration");
            request.AddParameter("client_id", LWA_App_ClientId);
            request.AddParameter("client_secret", LWA_App_ClientSecret);
            var response = client.Execute(request).Content;

            string token = JsonConvert.DeserializeObject<Token>(response).Access_Token;

            //step2: GET LWA
            client = new RestClient("https://sellingpartnerapi-eu.amazon.com");
            request = new RestRequest("authorization/v1/authorizationCode", Method.GET);
            request.AddQueryParameter("sellingPartnerId", "XXXXXXXXXXXXX");
            request.AddQueryParameter("developerId", "YYYYYYYYYYY");
            request.AddQueryParameter("mwsAuthToken", "amzn.ZZZZZZZZZZZZZZZZZZZ");

            request = SignWithAccessTokenMigration(request, LWA_App_ClientId, LWA_App_ClientSecret, token);
            request = SignWithSTSKeysAndSecurityTokenn(request, client.BaseUrl.Host, RoleARN, AWSKey, AWSSecret);
            response = client.Execute(request).Content;

response = 
{
  "errors": [
    {
      "code": "InvalidInput",
      "message": "A published application with the provided app-id not found",
      "details": ""
    }
  ]
}

What difference could there be between the 2 algorithms?
nicole1567 commented 3 years ago

我碰到的问题是,在我自己的开发机器上,用C# 写的exe, 设置的代理服务器, 能够正常跑,访问到Amazon的站点并得到order数据。 但是当我们放到一台DMZ區的機器要訪問Amazon的資料时, 却一直报错,这台机器的防火墙已经开通了对Amazon的站点权限。 报错信息是这样的, 有人知道是什么原因吗? System.AggregateException: One or more errors occurred. ---> Amazon.Runtime.AmazonServiceException: A WebException with status ConnectFailure was thrown. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xx.xx.xxx.xxx:443 at System.Net.Sockets.Socket.InternalEndConnect(IAsyncResult asyncResult) at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 promise, Boolean requiresSynchronization) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.HttpRequest.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.HttpHandler`1.d91.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Amazon.Runtime.Internal.HttpHandler1.d9`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.Unmarshaller.d31.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.ErrorHandler.<InvokeAsync>d__51.MoveNext() --- End of inner exception stack trace --- at Amazon.Runtime.Internal.WebExceptionHandler.HandleException(IExecutionContext executionContext, WebException exception) at Amazon.Runtime.Internal.ExceptionHandler1.Handle(IExecutionContext executionContext, Exception exception) at Amazon.Runtime.Internal.ErrorHandler.ProcessException(IExecutionContext executionContext, Exception exception) at Amazon.Runtime.Internal.ErrorHandler.<InvokeAsync>d__51.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.CallbackHandler.d9`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.EndpointDiscoveryHandler.d21.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Amazon.Runtime.Internal.EndpointDiscoveryHandler.<InvokeAsync>d__21.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.CredentialsRetriever.d7`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.RetryHandler.d101.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Amazon.Runtime.Internal.RetryHandler.<InvokeAsync>d__101.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.CallbackHandler.d9`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.CallbackHandler.d91.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__51.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.MetricsHandler.d__11.MoveNext() --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at CompanyXX.AmazonSPAPI.ConsoleApp.RequestSign.SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, String host, AmazonAPICredentials credentials) at CompanyXX.AmazonSPAPI.ConsoleApp.ApiProcess.createReport(AmazonAPICredentials credentials, String reportTypeIn, String dateFrom, String dateTo) ---> (Inner Exception #0) Amazon.Runtime.AmazonServiceException: A WebException with status ConnectFailure was thrown. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xx.xx.xxx.xxx:443

4SELLERS-Amazon commented 3 years ago

step1:get access_token

var client = new RestClient(Amazon_AuthUrl);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
//sellingpartnerapi::migration. For the Authorization API.
request.AddParameter("scope", "sellingpartnerapi::migration");
request.AddParameter("client_id", you client id);
request.AddParameter("client_secret", you client Secret);
client.Execute(request)

step2: GET LWA

new RestClient("https://sellingpartnerapi-na.amazon.com")
RestRequest request = new RestRequest("/authorization/v1/authorizationCode", Method.GET);
request.AddQueryParameter("sellingPartnerId", xxx1);
request.AddQueryParameter("developerId", xxx2);
request.AddQueryParameter("mwsAuthToken", xxx3);
request.AddHeader("x-amz-access-token", step 1 access-token);

AWSAuthenticationCredentials aws = new AWSAuthenticationCredentials()
{
    AccessKeyId = XXX,
    SecretKey = XXX,
    Region = "us-east-1"
};
AWSSigV4Signer signer = new AWSSigV4Signer(aws);
signer.Sign(request, client.BaseUrl.Host);

client.Execute(request)

step 3:Use LWA to get access-token\refresh-token

I got the authorizationCode from step 2 but how can I get the access-token\refresh-token from LWA with the authorizationCode?

Javadebi commented 3 years ago

step1:get access_token

var client = new RestClient(Amazon_AuthUrl);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
//sellingpartnerapi::migration. For the Authorization API.
request.AddParameter("scope", "sellingpartnerapi::migration");
request.AddParameter("client_id", you client id);
request.AddParameter("client_secret", you client Secret);
client.Execute(request)

step2: GET LWA

new RestClient("https://sellingpartnerapi-na.amazon.com")
RestRequest request = new RestRequest("/authorization/v1/authorizationCode", Method.GET);
request.AddQueryParameter("sellingPartnerId", xxx1);
request.AddQueryParameter("developerId", xxx2);
request.AddQueryParameter("mwsAuthToken", xxx3);
request.AddHeader("x-amz-access-token", step 1 access-token);

AWSAuthenticationCredentials aws = new AWSAuthenticationCredentials()
{
    AccessKeyId = XXX,
    SecretKey = XXX,
    Region = "us-east-1"
};
AWSSigV4Signer signer = new AWSSigV4Signer(aws);
signer.Sign(request, client.BaseUrl.Host);

client.Execute(request)

step 3:Use LWA to get access-token\refresh-token

where can i find my client_id and client_secret?

jamesaq12wsx commented 3 years ago

@Javadebi Those should be on your seller central LWA client and secret.

Javadebi commented 3 years ago

@Javadebi Those should be on your seller central LWA client and secret.

Thank you. In the first step i get invalid scope error. Do you know Why?

rugved1991 commented 2 years ago

Please reopen if this issue is not resolved.

Rugved Solutions Architect, SP API