AWS Item LookUp URL Signature - c#

I'm new to AWS, I'm trying to lookup an item by UPC within my UWP App. I'm having issues adding the signature to the request URL. I keep receiving "The request signature we calculated does not match the signature you provided."
Has any had any experience with making calls to Amazon? There api documentation isn't really aimed towards C# in most places.
public async void ItemLookup(string itemID)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("AssociateTag", associateTag);
fields.Add("Condition", "All");
fields.Add("IdType", "UPC");
fields.Add("ItemId", itemID);
fields.Add("Operation", "ItemLookup");
fields.Add("ResponseGroup", "Large");
fields.Add("SearchIndex", "All");
fields.Add("Service", "AWSECommerceService");
// fields.Add("Timestamp", Uri.EscapeDataString(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sssZ")));
// Build Url for signing
string url = string.Empty;
foreach (var pair in fields)
{
url += "&" + pair.Key + "=" + pair.Value;
}
url = Uri.EscapeUriString(endpoint
+ "AWSAccessKeyId=" + accessKeyId
+ url);
// Add Timestamp
url += "&Timestamp=" + Uri.EscapeDataString(DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture));
// URL http://webservices.amazon.co.uk/onca/xml?AWSAccessKeyId=REMOVED&AssociateTag=REMOVED&Condition=All&IdType=UPC&ItemId=786936724943&Operation=ItemLookup&ResponseGroup=Large&SearchIndex=All&Service=AWSECommerceService&Timestamp=2017-11-22T11%3A34%3A42.602Z
// SCRATCHPAD http://webservices.amazon.co.uk/onca/xml?AWSAccessKeyId=REMOVED&AssociateTag=REMOVED&Condition=All&IdType=UPC&ItemId=786936724943&Operation=ItemLookup&ResponseGroup=Large&SearchIndex=All&Service=AWSECommerceService&Timestamp=2017-11-22T09%3A20%3A35.000Z
// &Signature=Lvqlenpx0wos4Hg6ZzSNHqOc1QwktXgt8nFHBTfTON4%3D
Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(secretKey);
HMACSHA256 hmac = new HMACSHA256(secretBytes);
Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(url);
Byte[] hash = hmac.ComputeHash(dataBytes);
String signature = Convert.ToBase64String(hash);
// Full URL
string requestURL = url + "&Signature=" + signature;
HttpClient httpClient = new HttpClient();
HttpResponseMessage responseMessage = await httpClient.GetAsync(requestURL);
var response = await responseMessage.Content.ReadAsStringAsync();
}
}
I have the url from amazon scratchpad commented out against my own url, they are aligned but I'm not 100% sure if I'm working on the signature correctly.
Any help would be greatly appreciated
Kevin

I haven't tested the following yet. But there are doc about what you ruquest. Have you checked the following to create your signature?
First, the whole process listed here told us that you need to use a signed URL
Second, for how to create a URL Signature Using C# and the .NET, you can refer to the following doc: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateSignatureInCSharp.html
By the way, you can check the example code first.

You can use the following nuget package.
PM> Install-Package Nager.AmazonProductAdvertising
Lookup example
var authentication = new AmazonAuthentication();
authentication.AccessKey = "accesskey";
authentication.SecretKey = "secretkey";
var wrapper = new AmazonWrapper(authentication, AmazonEndpoint.UK);
var result = wrapper.Lookup("B00BYPW00I");

Related

HttpClient not returning json value of URI

I am trying to use HttpClient to GET information from Jira, but I am unable to see any of the information. I want to be able to get all the bugs that match certain filters so that I can add them to a table in my program.
I have tried to access Jira with the rest api, but every time I do it says that the issue or project doesn't exist. The thing is that if I enter the URI into the bar at the top of my browser I can see the JSON text that I want. This leads me to believe that the reason my code is not returning these values is because of an authorization issue. I am using basic auth to send my credentials. I also want to add that I used cURL in cmd to test my credentials with basic auth and it worked.
public async Task<JiraModel> GetBugs()
{
using (var client = new HttpClient())
{
string url = "https://myurl.atlassian.net/rest/api/3/project/VCMF";
String username = "username";
String password = "apikey";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(username + ":" + password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Basic " + encoded);
client.BaseAddress = new Uri("https://myurl.atlassian.net/rest/api/3/project/VCMF");
var response = await client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<JiraModel>(content);
}
}
I should be getting the json results in string form by the end of this length of code, but I keep getting a 404 error instead that for this code specifically says "No project could be found with key 'VCMF'".
The issue here is that you're creating the authorization header incorrectly.
The constructor you're using for AuthenticationHeaderValue class takes two arguments: scheme and parameter:
public AuthenticationHeaderValue(string scheme, string parameter)
{
}
The first argument should be the scheme (Basic in this case) and the second, the base64-encoded credentials:
So instead of:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Basic " + encoded);
It should be:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);
Hope this helps!

instagram api. hot to get the user's list of subscribers?

using the instagram documents I try to count user's list of subscribers.token is returned correctly, but if I try to get the users's list it's always error 400 code.
if someone found how to fix that tell me please how. I tryed with the instasharp but can not figured out how to use 'subscribers output method'. the internet has no good example with the explains for the beginner. using a library xNet
public string tok = Gettoken();
private void button1_Click(object sender, EventArgs e)
{
File.WriteAllText("tokken.txt", followby());
//MessageBox.Show(Gettoken());
}
public static string Gettoken()
{
string clientID = "**********************";
string clientSecret = "****************";
string redirect_uri = "https://localhost";
var info = "https://api.instagram.com/oauth/authorize/?client_id=" + clientID + "&redirect_uri=" + redirect_uri + "&response_type=token";
var request = new HttpRequest();
request.UserAgent = HttpHelper.ChromeUserAgent();
HttpResponse response = request.Get(string.Format(info));
string str = response.ToString();
string pattern = #"([0-9a-f]{32})";
Regex regex = new Regex(pattern);
Match match = regex.Match(str);
return match.Groups[1].Value.ToString();
}
string followby()
{
var info = "https://api.instagram.com/v1/users/23423443/follows?access_token=" + tok;
var request = new HttpRequest();
request.UserAgent = HttpHelper.ChromeUserAgent();
HttpResponse response = request.Get(string.Format(info)); //error
return response.ToString();
}
I believe you haven't included the permission scope of your application while getting your access token. I see you're trying to get the users' Follows and Followed-By list. For this you need to include "&scope=follower_list" in your URL for obtaining access token.
User will be asked that your application is trying to read your Follow list, if the user approves only then you can get this type of data.
Read https://www.instagram.com/developer/authorization/ for further information.

How to avoid escaping character in RestSharp?

I am writing a small application that sends data to a server through REST API as simple URL calls. I use the RestSharp library to do this. My problem is, that some data strings I am sending include the / character.
I can't leave the character as it is, since the called URL would then be invalid. But when I replace it with %2F (which is then translated back on the server side), the RestSharp replaces the % character again, giving %252F. The Rest call than fails since server is missing the backslash.
I have searched the web but found no working solution to this problem. Do you have any idea how to solve it, without using different library and rewriting it myself? Also, not using the backslash is NOT an option.
My code is here:
using RestSharp; //Version 104
private string RestRequest(string URL, RestSharp.Method Method)
{
var Client = new RestClient();
Client.Authenticator = new HttpBasicAuthenticator(ID, Password);
var Request = new RestRequest(URL, Method);
IRestResponse Response = Client.Execute(Request);
return Response.Content;
}
Sample URL that is passed to the function:
htp://localhost:8080/api/jsonws/knowledge-base-portlet.kbarticle/add-kb-article/portlet-id/1_WAR_knowledgebaseportlet/parent-resource-class-name-id/20704/parent-resource-prim-key/20200/title/SomeTitle/url-title/%2FTitle/content/SomeContent
After snooping around Resharper's Github issues, like this one, it seems you have to use RestRequest.AddURLSegment(). Tested with RestSharp v. 104.0.0
var url = "http://localhost:4422/api/jsonws/knowledge-base-portlet.kbarticle/add-kb-article/portlet-id/1_WAR_knowledgebaseportlet/parent-resource-class-name-id/20704/parent-resource-prim-key/20200/title/SomeTitle/url-title/{segment}/content/SomeContent";
var Client = new RestClient();
var Request = new RestRequest(url,Method.GET);
Request.AddUrlSegment("segment", "%2Ftitle");
I don't know if it's possible for you to pass multiple arguments. If you cannot, the simplest scenario would be splitting by %2F and concatenate multiple arguemnts. Something like this:
private string RestRequest(string URL, RestSharp.Method Method)
{
var Client = new RestClient();
string requestUrl;
bool hasBackslashArgument = ParseEncodedBackSlash(URL, out requestUrl);
RestRequest request;
if (hasBackslashArgument)
{
request = new RestRequest(requestUrl, Method);
request.AddUrlSegment("segment", "%2F");
}
else
{
request = new RestRequest(URL, Method);
}
IRestResponse response = Client.Execute(request);
return response.Content;
}
private bool ParseEncodedBackSlash(string url, out string preformattedString)
{
preformattedString = null;
var urlSegments = url.Split(new string[] { "%2F" }, StringSplitOptions.None);
if (urlSegments.Length == 0) return false;
preformattedString = string.Join("{segment}", urlSegments);
return true;
}

Making POST API request via c# with hashed API Key

I'm trying to make a POST call (from a C# WPF app) to a web service on an internal intranet (so I can't give the exact URL sorry), which is basically a url shortening service.
The page gives the following instructions:
In order to use the API service, simply make HTTP POST requests to this URL:
https://...internalAddress.../api/<method>
For example, to create a snip, make an HTTP POST request to:
https://...internalAddress.../api/shorten
with these parameters:
api_key hash of a registered API key
url URL to be shortened
Now I have tried to implement this in a couple of different ways with what I've found via google / here, these are:
1:
string apiKey = "xxxx11112222333";
string urlForShortening = #"http://www.codeproject.com/Tips/497123/How-to-make-REST-requests-with-Csharp";
string destination = #"https://internalurl/api/shorten";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(destination);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write("{'api_key': '" + apiKey + "', 'url': '" + urlForShortening + "'}");
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
MessageBox.Show(responseText);
}
2: (Using the rest library created in the article found in the shortening link)
string apiKey = "xxxx11112222333";
string urlForShortening = #"http://www.codeproject.com/Tips/497123/How-to-make-REST-requests-with-Csharp";
string destination = #"https://internalurl/api/shorten";
RestClient client = new RestClient(destination, HttpVerb.POST,
"{'api_key': '" + apiKey + "', 'url': '" + urlForShortening + "'}");
var json = client.MakeRequest();
MessageBox.Show(json);
have also tried feeding in the jsonData in double quotes:
var jsonData = "{\"api_key\": \"" + apiKey + "\", \"url\": \"" + urlForShortening + "\"}";
The result from both methods I always get is:
{"status": 400, "message": "Missing API key"}
Can someone please shed some light on what I'm doing wrong?
From the brief, I think the key may need to be hashed in some form and not sure how to do this.
Turns out my whole implementation was wrong, I was trying to send the data as JSON / using the wrong classes instead of a vanilla HTTP POST.
I used Method 2 found in this article and it worked fine: HTTP request with post
ie.
using (var client = new WebClient())
{
var values = new NameValueCollection();
values["api_key"] = "xxxx11112222333";
values["url"] = #"http://www.codeproject.com";
string destination = #"https://internalurl/api/shorten";
var response = client.UploadValues(destination, values);
var responseString = Encoding.Default.GetString(response);
MessageBox.Show(responseString);
}
Thanks for your help though!
I assume that you are attempting to send json data in the request body for the POST call to the API.
You dont seem to be providing a valid json here though. This is what you are sending now:
{'api_key':'someApiKey'}
{'url':'someUrlForShortening'}
Use a json validator to ensure you have a valid json document before you attempt to send it to the API.
A valid json would be
{
"api_key":"someApiKey",
"url":"someUrlForShortening"
}

Yahoo Oauth API with OAuthBase.cs

I am currently using the OAuthBase.cs helper class available on oauth.net to implement OAuth to talk to the Yahoo! fantasy API. I am currently stuck on Step 5 (Using the access token/access secret to call the API Services).
I successfully completed Step 4 but cannot seem to create the actual service call. The documentation is limited; what parameters am I supposed to be using? I'm getting either a 401 or 400 http error. I'm generating my signature by:
url = new Uri("http://query.yahooapis.com/v1/public/yql?q=select * from fantasysports.teams.roster.stats where team_key='nba.l.52669.t.5' and week='5' and stats_type='week' and stats_week='5'&format=json");
signature = oauth.GenerateSignature(url, string.Empty, consumerKey, consumerSecret, accessToken, accessTokenSecret, "GET", time, string.Empty, nonce, OAuth.OAuthBase.SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
using (var y = WebRequest.Create(string.Format("{0}?{1}&oauth_signature={2}", normalizedUrl, normalizedRequestParameters, signature)).GetResponse())
{
....
}
where url is the api call i'm trying to make, consumerKey / consumerSecret are the keys given to me when I signed up for Yahoo!, and accessToken / accessTokenSecret are the response returned from request_auth in Step 4. What am I doing wrong?
Thanks in advance
EDIT: 12/14 - for those not familiar with OAuthBase, it is essentially a library that generates the signature by
1. Consolidating all the url/parameters (consumerkey, token, tokenSecret, httpMethod, nonce, time etc), sorting it, and normalizing the url/parameters;
2. Encodes the consumerSecret '&' tokenSecret as the HMACSHA1 key;
3. computing the hash of the hmacsha1 key
Here is some working code for accessing a Yahoo API using OAuth (in this case the BOSS Geo API)
[Test]
public void MakeCallToBossGeoApi()
{
string result;
var uri = new Uri(#"http://yboss.yahooapis.com/geo/placefinder?country=SE&flags=J&locale=sv_SE&postal=41311");
var o = new OAuthBase();
string nonce = o.GenerateNonce();
var timestamp = o.GenerateTimeStamp();
string normalizedUrl;
string normalizedParameters;
string signature = HttpUtility.UrlEncode(
o.GenerateSignature(uri,
"yourconsumerkeyhere",
"yourconsumersecrethere", null, null, "GET",
timestamp, nonce, out normalizedUrl,
out normalizedParameters));
uri = new Uri(normalizedUrl +"?"+ normalizedParameters + "&oauth_signature=" + signature );
using (var httpClient = new WebClient())
{
result = httpClient.DownloadString(uri.AbsoluteUri);
}
Console.WriteLine(result);
}

Categories