Amazon MWS client library C# AWS Access Key Id error - c#

I am using Amazon C# client library to get product information and keep getting an error " The AWS Access Key Id you provided does not exist in our records." (Yes, I tried the seller forum, but didn't get an answer there). When I use the same Access Key using their scratchpad, I get the correct response. I did see this post (Getting 'The AWS Access Key Id you provided does not exist in our records' error with Amazon MWS) and tried swapping the parameters and that didn't work. Here is my C# code. Any help would be greatly appreciated
string AccessKey = "xxx";
string SecretKey = "xxx";
string AppName = "ProductFunctionsApp";
string AppVersion = "1.0";
string ServiceURL = "https://mws.amazonservices.com/Products/2011-10-01";
string SellerId="xxxx";
string MarketPlaceId = "xxx";//US
//right now MWSAuthToken is only if a developer is using a sellers account
MarketplaceWebServiceProductsConfig config = new MarketplaceWebServiceProductsConfig();
config.ServiceURL = ServiceURL;
config.SignatureMethod = "HmacSHA256";
config.SignatureVersion = "2";
MarketplaceWebServiceProductsClient client = new MarketplaceWebServiceProductsClient(AppName, AccessKey, SecretKey, AppVersion, config);
ASINListType type = new ASINListType();
List<string> ASINList = new List<string>();
ASINList.Add("B001E6C08E");
type.ASIN = ASINList;
;
GetCompetitivePricingForASINRequest request = new GetCompetitivePricingForASINRequest();
request.SellerId = SellerId;
request.ASINList = type;
request.MarketplaceId = MarketPlaceId;
GetCompetitivePricingForASINResponse response = client.GetCompetitivePricingForASIN(request);

Some of their API Clients have the class initialization parameters defined in different orders.
So if you copy and paste the initialization code you'll end up with the application name being sent instead of the access key.
var service = new MarketplaceWebServiceProductsClient(
applicationName, applicationVersion, accessKeyId, secretAccessKey, config);
And it's different here:
var service = new FBAInventoryServiceMWSClient(
accessKeyId, secretAccessKey, applicationName, applicationVersion, config);
Just check each one carefully.

Related

How do you Create Restricted Data Token Request using Amazon Selling Partner API C#?

I am trying to get PII information for the FileAmazonAPI.AmazonConnection.Tokens.CreateRestrictedDataToken method using Amazon Selling Partner API C#. I was successful creating temporary access credentials using Amazon.SecurityToken.IAmazonSecutiryTokenService by creating an assumeRoleResponse. The assumeRoleReponse looks like this.
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<AssumedRoleId>AROAXXXXXXXXXXXXXXXXX:Test</AssumedRoleId>
<Arn>arn:aws:sts::XXXXXXXXXXXX:assumed-role/MyRole/Test</Arn>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>ASIAXXXXXXXXXXXXXXXX</AccessKeyId>
<SecretAccessKey>p4hqj/XXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</SecretAccessKey>
<SessionToken>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</SessionToken>
<Expiration>2022-11-07T18:05:53Z</Expiration>
</Credentials>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>87740b15-a528-41a1-8de9-XXXXXXXXXXXX</RequestId>
</ResponseMetadata>
I then configured my AmazonConnection by using the accessKey, SecretKey and RefreshToken from the assumeRoleResponse.
AmazonConnection amazonConnection = new AmazonConnection(new AmazonCredential()
{
AccessKey = assumeRoleResponse.Credentials.AccessKeyId,
SecretKey = assumeRoleResponse.Credentials.SecretAccessKey,
RoleArn = _roleArn,
ClientId = _clientId,
ClientSecret = _clientSecret,
RefreshToken = assumeRoleResponse.Credentials.SessionToken,
MarketPlace = MarketPlace.US,
});
Created the CreateRestrictedDataTokenRequest Object
CreateRestrictedDataTokenRequest rdtRequest = new CreateRestrictedDataTokenRequest()
{
restrictedResources = new List<RestrictedResource>
{
new RestrictedResource
{
method = Method.GET.ToString(),
path = ApiUrls.OrdersApiUrls.Orders,
dataElements = new List<string> { "buyerInfo", "shippingAdress" }
}
}
};
Then called the CreateRestrictedDataTokenMethod
CreateRestrictedDataTokenResponse createRestrictedDataTokenResponse = amazonConnection.Tokens.CreateRestrictedDataToken(rdtRequest);
This is where I get the error "Error getting LWA Access Token". Am I not passing the correct accessKey and secretKey in my AmazonConnection? I do have access rights on my Amazon Developer Account for Direct-to-Consumer-Shipping role.
Can anyone please assist?
Thanks in advance

How to create CallCredentials from SslCredentials and token string

I am porting a gRPC client from python to c#. Both the python client and the c# client are using the gRPC Framework from grpc.io.
The python client uses the following code to open a secure, non-authenticated channel, which it then uses to procure a token string, which it then uses to create call credentials with the grpc.composite_channel_credentials() function:
channel = grpc.secure_channel(url_server_address, ssl_creds)
stub = gateway.GatewayStub(channel)
# Acquire access token via password authentication
pw_cmd = gateway.PasswordAuthenticateCmd(account_name=url.username, password=url.password)
auth_rsp = stub.PasswordAuthenticate(pw_cmd)
# Open a secure, authenticated channel
auth_creds = grpc.access_token_call_credentials(auth_rsp.access_token)
composite_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
channel = grpc.secure_channel(url_server_address, composite_creds)
stub = gateway.GatewayStub(channel)
In c#, I have been able to compile the protocol buffer definitions, and connect with the generated client to successfully acquire the access token:
SslCredentials secureChannel = new SslCredentials(File.ReadAllText(SSLCertificatePath));
Channel channel = new Channel(ServerURL, PortNum, secureChannel);
var client = new GrpcClient(new Grpc.Gateway.GatewayClient(channel));
var response = client.client.PasswordAuthenticate(new PasswordAuthenticateCmd() { AccountName = UserName, Password = UserPassword });
Console.WriteLine(response.AccessToken);
From here, however, I can't find the c# analog to the grpc.composite_channel_credentials() function to take the SslCredentials and the access token string to create combined credentials.
None of the examples here https://grpc.io/docs/guides/auth.html here use a token string, and I haven't been able to find any other examples out there.
What you're looking for is:
https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Core/CallCredentials.cs#L49 and https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Core/ChannelCredentials.cs#L67.
Feel free to also look at:
https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs#L58
I solved my problem using CallCredentials.FromInterceptor().
The grpc.access_token_call_credentials() python call adds an authorization entry to the metadata, and sets its value to "Bearer " + AccessToken, so I just had to do the same:
SslCredentials secureCredentials = new SslCredentials(File.ReadAllText(SSLCertificatePath));
Channel secureChannel = new Channel(ServerURL, PortNum, secureCredentials);
var client = new GrpcClient(new Grpc.Gateway.GatewayClient(secureChannel));
var response = client.client.PasswordAuthenticate(new PasswordAuthenticateCmd() { AccountName = UserName, Password = UserPassword });
var accessTokenCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) =>
{
metadata.Add("authorization", "Bearer " + passwordResponse.AccessToken);
return TaskUtils.CompletedTask;
}));
var authenticatedCredentials = ChannelCredentials.Create(secureCredentials, accessTokenCredentials);
Channel authenticatedChannel = new Channel(hostURL, hostPort, authenticatedCredentials);
As Jan pointed out in his answer, there is a function in the Grpc.Auth namespace that does the same thing as the function that I wrote: https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs#L58

DocuSign API and DocumentPDFs docPDFs = apiService.RequestDocumentPDFs(envelopeID);

I am using the code below to connect to DocuSign API.
WHAT AM I doing wrong, I keep getting Username and Password not correct when they are!
String auth = "<DocuSignCredentials><Username>john.connolly#lechase.com</Username><Password>password</Password><IntegratorKey>20be051c-4c25-46c1-b0f1-1f10575a2e40</IntegratorKey></DocuSignCredentials>";
DSAPIServiceSoapClient client = new DSAPIServiceSoapClient("DSAPIServiceSoap");
using (System.ServiceModel.OperationContextScope scope = new System.ServiceModel.OperationContextScope(client.InnerChannel))
{
System.ServiceModel.Channels.HttpRequestMessageProperty httpRequestProperty = new System.ServiceModel.Channels.HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", auth);
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus status = client.RequestStatusEx("12d46951-1f1c-48cd-9a28-e51685d67ccd");
Console.Out.WriteLine("Subject: " + status.Subject);
}
Since you use the (Legacy Header Authentication uses the X-DocuSign-Authentication header):
Use the Authentication: login method
to retrieve the account number and the baseUrl for the account.
The url for the login method is www.docusign.net for production and
demo.docusign.net for the developer sandbox. The baseUrl field is
part of the loginAccount object. See the docs and the loginAccount
object
The baseUrl for the selected account, in production, will start with na1, na2, na3, eu1, or something else. Use the baseUrl that is
returned to create the basePath (see the next step.) Use the
basePath for all of your subsequent API calls.
As returned by login method, the baseUrl includes the API version and account id. Split the string to obtain the basePath, just the
server name and api name. Eg, you will receive
https://na1.docusign.net/restapi/v2/accounts/123123123. You want
just https://na1.docusign.net/restapi
Instantiate the SDK using the basePath. Eg ApiClient apiClient = new ApiClient(basePath);
Set the authentication header as shown in the examples by using Configuration.Default.AddDefaultHeader Ref.
Sample Code: Try a verbatim string for your auth string.
string auth = #"<DocuSignCredentials>
<Username>john.connolly#lechase.com</Username>
<Password>S3cre+p455w0Rd</Password>
<IntegratorKey>20be051c-4c25-46c1-b0f1-1f10575a2e40</IntegratorKey>
</DocuSignCredentials>";
DSAPIServiceSoapClient apiService = new DSAPIServiceSoapClient();
using (var scope = new System.ServiceModel.OperationContextScope(apiService.InnerChannel))
{
var httpRequestProperty = new System.ServiceModel.Channels.HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", auth);
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus envStatus = apiService.CreateAndSendEnvelope(envelope);
return envStatus.EnvelopeID;
}

Amazon S3 Unable to find credentials in C#

I'm trying to upload an image file to aws s3 storage and get back that image URL. I'm using secret key and access key to create credentials. But when the program runs it it says
"Unable to find credentials" .
Here is my code which i used.
public string sendMyFileToS3(string from,string to, string bucketName, string fileName)
{
BasicAWSCredentials awsCreds = new BasicAWSCredentials(bucketName, fileName);
AmazonS3Client client = new AmazonS3Client(awsCreds);
TransferUtility utility = new TransferUtility(client);
TransferUtilityUploadRequest request = new TransferUtilityUploadRequest();
request.BucketName = bucketName;
request.Key = fileName;
request.FilePath = from;
utility.Upload(request);
string urlString = "";
GetPreSignedUrlRequest request1 = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = fileName,
Expires = DateTime.Now.AddYears(2)
};
urlString = client.GetPreSignedURL(request1);
Console.WriteLine(urlString);
File.Move(from, to);
return urlString ;
}
In order to create an S3 Client you need to provide your credentials, the region and endpoint:
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3Config config = new AmazonS3Config();
config.ServiceURL = "s3.amazonaws.com";
config.RegionEndpoint = Amazon.RegionEndpoint.GetBySystemName("us-east-1");
client = new AmazonS3Client(credentials, config);
The possible regions are listed here, and depend on where you created your bucket being us-east-1 the default value.
While the possible endpoints are this three:
s3.amazonaws.com
s3-accelerate.amazonaws.com
s3-accelerate.dualstack.amazonaws.com
The first one being the standard one since the others need you to configure your bucket like it's explained here.
I am going to take a guess and say you have a conflict between the credentials your app is using and other credentials you may have installed onto your dev or test machine, i.e. in the credentials file or your app.config.
I would check and make sure you are only using a single method to provide those credentials to the program.
THis link shows the priority the SDK will look for the credentials:
http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html

Amazon S3 : List Objects

I have this code to list objects in the folder.
var accessKey = ConfigurationManager.AppSettings["AWSAccessKey"];
var secretKey = ConfigurationManager.AppSettings["AWSSecretKey"];
using (AmazonS3Client s3Client = new AmazonS3Client(accessKey, secretKey, RegionEndpoint.USEast1 ))
{
var prefix = string.Format(#"{0}/", uniqueKey);
ListObjectsRequest request = new ListObjectsRequest();
request.BucketName = bucketName;
request.Delimiter = "/";
request.Prefix = prefix;
do
{
ListObjectsResponse response = s3Client.ListObjects(request);
This throws an exception when I access the folders :
<uri>/bucketname/profile/ // Throws and exception key not found
<uri>/bucketname/profile/profile.png // This is OK
Image was created using the following path having a READ CannedACL.
<uri>/bucketname/profile//profile.png
Error
String key was not found
QUESTION
Why i cannot access the folders (objects)?
Are folders need to set permissions individually for it to be accessible?
UPDATE
I solved the issue
Bucket names should not have a / character
Client given me a bucket name with this format sample/new
But the true bucket name is only sample

Categories