Create Table in Azure using REST API - c#

Has anyone tried creating a table inside a storage account using REST API? I can do it without an issue if I use SharedKeyLite authorization. However, when using SharedKey authorization, the authentication keeps on failing.
My guess is it's got to do something with the "Content-MD5" value in the Authorization signature. The documentation is a little vague on Content-MD5 value and I can't find a recommended way to generate Content-MD5 in the documentation.
I can't find an example using C#. The only example I found was using Powershell and that is using an empty string for Content-MD5. However, that doesn't work for my case.
Here is my code:
public static void CreateTable(string storageAccount, string storageKey, string tableName)
{
var client = new HttpClient();
string date = DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
client.DefaultRequestHeaders.Add("x-ms-date", date);
string msVersion = "2018-03-28";
client.DefaultRequestHeaders.Add("x-ms-version", msVersion);
client.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0;NetFx");
client.DefaultRequestHeaders.Add("DataServiceVersion", "3.0;NetFx");
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=nometadata");
string payload = "{ \"TableName\":\""+ tableName +"\" }";
int contentLength = GetContentLength(payload);
string authH = "SharedKey " + storageAccount + ":" + CreateTableSignature("POST", payload, "application/json", date, storageAccount + "/Tables", storageKey, new List<string>() { });
client.DefaultRequestHeaders.Add("Authorization", authH);
string requestUri = $"https://{storageAccount}.table.core.windows.net/Tables";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri);
request.Content = new StringContent(payload,
Encoding.UTF8,
"application/json");
request.Content.Headers.ContentLength = contentLength;
client.SendAsync(request)
.ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
}
public static string CreateTableSignature(string verb, string content, string contentType, string date, string resource, string key, List<string> canonicalizedResourceParms)
{
string msgSignature = verb + "\n" +
CreateMD5(content) + "\n" +
contentType + "\n" +
date + "\n";
msgSignature += "/" + resource;
foreach (string parm in canonicalizedResourceParms)
msgSignature += "\n" + parm;
byte[] SignatureBytes = Encoding.UTF8.GetBytes(msgSignature);
// Create the HMACSHA256 version of the storage key.
HMACSHA256 SHA256 = new HMACSHA256(Convert.FromBase64String(key));
// Compute the hash of the SignatureBytes and convert it to a base64 string.
return Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
}
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToBase64String(hashBytes);
}
}

Two points to fix.
Content-Type
request.Content = new StringContent(payload,
Encoding.UTF8,
"application/json");
In this method, SDK actually sets application/json; charset=utf-8 when we sending the request. This means the signature needs application/json; charset=utf-8 as well.
Or I recommend you to remove that misleading content type setting and use
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Content-MD5
It's not required in signature, you can leave it empty. Otherwise If you want to put it in the signature, you need to add corresponding request header first.
request.Content.Headers.ContentMD5 = Convert.FromBase64String(CreateMD5(payload));
Besides, in method CreateMD5(), Encoding should be UTF8
System.Text.Encoding.UTF8.GetBytes(input);

Related

Access the Coinbase Candles url

I have successfully managed to call some of Coinbase API's end points, but struggling on calling the Candles Url:
using RestSharp;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
var symbol = "BTC-GBP";
var _privateApiKey = "xxxx";
var _secret = "xxxxxxxxxx";
var _timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
var _requestPath = "/api/v3/brokerage/products/" + symbol + "/candles";
var _method = "GET";
var client = new RestClient(#"https://api.coinbase.com" + _requestPath + "?granularity=ONE_DAY&start=" + DateTime.Now.AddMilliseconds(-3000).ToUniversalTime().Ticks + "&end=" + DateTime.Now.ToUniversalTime().Ticks + "");
var request = new RestRequest();
request.Method = Method.Get;
request.AddHeader("Content-Type", "application/json");
request.AddHeader("CB-ACCESS-KEY", _privateApiKey);
request.AddHeader("CB-ACCESS-TIMESTAMP", _timestamp);
request.AddHeader("CB-ACCESS-SIGN", GetAccessSign(_timestamp, _method, _requestPath, "", _secret));
request.AddHeader("CB-VERSION", "2023-01-18");
try
{
var response = client.Execute(request);
Console.WriteLine(response.Content);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
string GetAccessSign(string timestamp, string method, string path, string body, string apiSecret)
{
var convertedString = Convert.FromBase64String(apiSecret);
var hmaccsha = new HMACSHA256(convertedString);
string timestampStr = timestamp;
string httpMethodStr = method;
var prehash = timestampStr + httpMethodStr + path + body;
// Convert the input string and key to byte arrays
byte[] prehashBytes = Encoding.UTF8.GetBytes(prehash);
byte[] keyBytes = Encoding.UTF8.GetBytes(apiSecret);
// Compute the SHA-256 hash of the input data using the key
HMACSHA256 hmac = new HMACSHA256(keyBytes);
byte[] hash2 = hmac.ComputeHash(prehashBytes);
// Convert the hash to a hexadecimal string
string signedSignature = BitConverter.ToString(hash2).Replace("-", "").ToLower();
return signedSignature;
}
But i keep getting this error:
{"error":"INVALID_ARGUMENT","error_details":"start and end argument is invalid - number of candles requested should be less than 300 ","message":"start and end argument is invalid - number of candles requested should be less than 300 "}
You are missing the required arguments:
https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_getcandles
Path Params
product_id string required
The trading pair.
Query Params
start string required
Timestamp for starting range of aggregations, in UNIX time.
end string required
Timestamp for ending range of aggregations, in UNIX time.
granularity string required
The time slice value for each candle.
The API probably just has a bad error message and treats undefined start and end range query params as out of range values.
I managed to get the results back using this in the RestClient and to Tomáš Hübelbauer link:
var client = new RestClient(string.Format(#"https://api.coinbase.com" + _requestPath + "?granularity=ONE_MINUTE&start={0}&end={1}", DateTimeOffset.Now.AddSeconds(-6000).ToUnixTimeSeconds(), DateTimeOffset.Now.ToUnixTimeSeconds()));
Which gave me about 30 to 35 elements of data back

How to authenticate using C# when making calls to 2checkout API

I am trying to make a call to 2checkout API. According to their documentation first I need to authenticate. All example code on their website is written in PHP.
When I try the same using C# I am getting "Hash signature could not be authenticated" message from the server.
Here is code-snipped from my code:
Encoding encoding = Encoding.UTF8;
string vendorCode = //My vendor code
string secretKey = //My secret key
byte[] secretBytes = encoding.GetBytes(secretKey);
date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string input = vendorCode.Length.ToString() + vendorCode + date.Length.ToString() + date;
using (HMACMD5 keyedHash = new HMACMD5(secretBytes))
{
byte[] hashedBytes = keyedHash.ComputeHash(encoding.GetBytes(input));
string hash = Convert.ToBase64String(hashedBytes);
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, apiUrl +
requestString))
{
request.Headers.Add("accept", "application/json");
string headerValue = "code=\"" + vendorCode + "\" date=\"" + date + "\" hash=\"" + hash + "\"";
request.Headers.Add("X-Avangate-Authentication", headerValue);
HttpResponseMessage httpResponse = await httpClient.SendAsync(request);
}
}
I am not sure what I am doing wrong. Is it the hash algorithm that I use or it is the text encoding?
I tried several variants but without any success.
I will be very grateful if someone helps me with this.
The below code block works for me. Code slightly modified as per needs on basis of the documentation https://verifone.cloud/docs/2checkout/API-Integration/Webhooks/06Instant_Payment_Notification_%2528IPN%2529/IPN-code-samples#c__0023__00a0
string secretKey = "MYSECRETKEY";
string VendorCode = "MYVENDORCODE";
string requestDateTime = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
string plaintext = VendorCode.Length + VendorCode + requestDateTime.Length + requestDateTime;
using(HMACMD5 hmac = new HMACMD5(Encoding.ASCII.GetBytes(secretKey)))
{
byte[] hashBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(plaintext));
string signatureHash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
using (var httpClient = new HttpClient { BaseAddress = new Uri("https://api.avangate.com/rest/6.0/") })
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", "application/json");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Avangate-Authentication", $"code='{VendorCode}' date='{requestDateTime}' hash='{signatureHash}'");
// Make your requests to desired Api
}
}

HMAC validation Failure with code 403

I have been exploring payeezy api from last three days. I am just making a simple http web request from a C# application. I have followed all the steps mentions and correctly verified each and everything. Below is the detail per item.
API Key :- I have verified my api key its correct.
API Secret :- It is also correct.
merchant token :- It is also verified.
Nonce :- I have created cryptographically strong random number as following.
RandomNumberGenerator rng = new RNGCryptoServiceProvider();
byte[] nonceData = new byte[18];
rng.GetBytes(nonceData);
string nonce = BitConverter.ToUInt64(nonceData,0).ToString();
Timestamp :-
string timestamp = Convert.ToInt64(ts.TotalMilliseconds).ToString();
Payload :-
{"merchant_ref":"Astonishing-Sale","transaction_type":"authorize","method":"credit_card","amount":"1299","currency_code":"USD","credit_card":{"type":"visa","cardholder_name":"John Smith","card_number":"4788250000028291","exp_date":"1020","cvv":"123"}}
Then I have created HMAC as following.
private string CreateAuthorization(string data, string secret)
{
// data is in following format.
// data = apiKey + nonce + timestamp + token + payload;
secret = secret ?? "";
using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
byte[] hashdata = hmacsha256.ComputeHash(Encoding.UTF32.GetBytes(data));
return Convert.ToBase64String(hashdata);
}
}
Now I am getting hmac validation error. My generated hmac string is 64 bit while on your website under docs and sandbox its 86 bit.
Can you please assist me in this as I am stuck on this issue from last three days.
Thanks
These are the common causes for “HMAC validation Failure”:
API key and/or API secret are incorrect.
Leading or trailing spaces in the API key, API secret, merchant token.
Timestamp in the HTTP header is not in milliseconds.
Timestamp in the HTTP header does not represent EPOCH time.
Timestamp in the HTTP header is not within 5 minutes of our server time.
System time is not accurate.
Here is a sample c# code to generate HMAC:
public byte[] CalculateHMAC(string data, string secret)
{
HMAC hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] hmac2Hex = hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(data));
string hex = BitConverter.ToString(hmac2Hex);
hex = hex.Replace("-","").ToLower();
byte[] hexArray = Encoding.UTF8.GetBytes(hex);
return hexArray;
}
protected void Button1_Click(object sender, EventArgs e)
{
string jsonString = "{ \"merchant_ref\": \"MVC Test\", \"transaction_type\": \"authorize\", \"method\": \"credit_card\", \"amount\": \"1299\", \"currency_code\": \"USD\", \"credit_card\": { \"type\": \"visa\", \"cardholder_name\": \"Test Name\", \"card_number\": \"4005519200000004\", \"exp_date\": \"1020\", \"cvv\": \"123\" } }";
Random random = new Random();
string nonce = (random.Next(0, 1000000)).ToString();
DateTime date = DateTime.UtcNow;
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan span = (date - epoch);
string time = span.TotalSeconds.ToString();
string token = Request.Form["token"];//Merchant token
string apiKey = Request.Form["apikey"];//apikey
string apiSecret = Request.Form["apisecret"];//API secret
string hashData = apiKey+nonce+time+token+jsonString;
string base64Hash = Convert.ToBase64String(CalculateHMAC(hashData, apiSecret));
string url = "https://api-cert.payeezy.com/v1/transactions";
//begin HttpWebRequest
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.Accept = "*/*";
webRequest.Headers.Add("timestamp", time);
webRequest.Headers.Add("nonce", nonce);
webRequest.Headers.Add("token", token);
webRequest.Headers.Add("apikey", apiKey);
webRequest.Headers.Add("Authorization", base64Hash );
webRequest.ContentLength = jsonString.Length;
webRequest.ContentType = "application/json";
StreamWriter writer = null;
writer = new StreamWriter(webRequest.GetRequestStream());
writer.Write(jsonString);
writer.Close();
string responseString;
try
{
using(HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
using (StreamReader responseStream = new StreamReader(webResponse.GetResponseStream()))
{
responseString = responseStream.ReadToEnd();
request_label.Text = "<h3>Request</h3><br />" + webRequest.Headers.ToString() + System.Web.HttpUtility.HtmlEncode(jsonString);
response_label.Text = "<h3>Response</h3><br />" + webResponse.Headers.ToString() + System.Web.HttpUtility.HtmlEncode(responseString);
}
}
}
catch (WebException ex)
{
if (ex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
{
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
{
string remoteEx = reader.ReadToEnd();
error.Text = remoteEx;
}
}
}
}
}
I've been working on an integration and it's working great; maybe you can take a peek
https://github.com/clifton-io/Clifton.Payment
Specifically you'll want to look here:
https://github.com/clifton-io/Clifton.Payment/blob/cc4053b0bfe05f2453dc508e96a649fc138b973c/Clifton.Payment/Gateway/Payeezy/PayeezyGateway.cs#L66
Best of luck :)

API exception while calling 'DataWarehouseGetReportData' in C#

I am using Omniture api to download a report. The report is completed when I checked the status with DataWarehouseCheckRequest method. Now when I try to fetch the report using DataWarehouseGetReportData method, I get
CommunicationException Error in deserializing body of reply message for operation 'DataWarehouseGetReportData
Inner exception says
The specified type was not recognized: name='data_warehouse_report_row', namespace='http://www.omniture.com/', at <rows xmlns=''>
I am new with C# and the API both. Got no idea how to resolve this. Please help.
Thanks
When you want to download a DW report the best option is to do it over http. This the standard way and is much more efficient.
The response to CheckRequest contains a DataURL. Use that to download the data.
Here is some c# sample code I am using for an almost identical API (Partner vs you Enterprise API) (note I'm no c# expert either, so you will need to do a code review on this).
HttpWebResponse statusResponse = null;
string response = "";
StringBuilder sbUrl = new StringBuilder(dwrq.data_url); // hardcode to variable "rest_url" for testing.
HttpWebRequest omniRequest = (HttpWebRequest)WebRequest.Create(sbUrl.ToString());
string timecreated = generateTimestamp();
string nonce = generateNonce();
string digest = getBase64Digest(nonce + timecreated + secret);
nonce = base64Encode(nonce);
omniRequest.Headers.Add("X-WSSE: UsernameToken Username=\"" + username + "\", PasswordDigest=\"" + digest + "\", Nonce=\"" + nonce + "\", Created=\"" + timecreated + "\"");
omniRequest.Method = "GET"; // Switched from POST as GET is the right HTTP verb in this case
try
{
statusResponse = (HttpWebResponse)omniRequest.GetResponse();
using (Stream receiveStream = statusResponse.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
response = readStream.ReadToEnd();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
Console.WriteLine("Response is a TAB delimeted CSV structure. Printing to screen.");
Console.WriteLine(response);
Console.WriteLine("Ending REST...");
Console.WriteLine("Ending ExportRequestSegmentedData...");
and the supporting methods
/*** Here are the private functions ***/
// Encrypting passwords with SHA1 in .NET and Java
// http://authors.aspalliance.com/thycotic/articles/view.aspx?id=2
private static string getBase64Digest(string input)
{
SHA1 sha = new SHA1Managed();
ASCIIEncoding ae = new ASCIIEncoding();
byte[] data = ae.GetBytes(input);
byte[] digest = sha.ComputeHash(data);
return Convert.ToBase64String(digest);
}
// generate random nonce
private static string generateNonce()
{
Random random = new Random();
int len = 24;
string chars = "0123456789abcdef";
string nonce = "";
for (int i = 0; i < len; i++)
{
nonce += chars.Substring(Convert.ToInt32(Math.Floor(random.NextDouble() * chars.Length)), 1);
}
return nonce;
}
// Time stamp in UTC string
private static string generateTimestamp()
{
return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
}
// C#-Base64 Encoding
// http://www.vbforums.com/showthread.php?t=287324
public static string base64Encode(string data)
{
byte[] encData_byte = new byte[data.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
Best of Luck! C.

Invalid signature for signing requests to the Flickr API (simulation in console)

I'm trying to authenticate to the Flickr API for a demo application I want to make for myself. Then i will extend this app with new features that i'll learn of the Flick API's.
So this is just something i want to play with. But now I have some trouble in getting a request token.
I'm following the Flickr Authentication documentation here: Flickr Authentication
And i also found this Mathlabscript: Flickr API with OAuth-based user authentication
So based on these sources i have now the following console application:
class Program
{
private static string Secret = "2b2b2b2b2b2b2b2b2b";
private static string ConsumerKey = "1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a";
static void Main(string[] args)
{
Random rand = new Random();
string nonce = rand.Next(9999999).ToString();
string timestamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
Console.WriteLine("Nonce: " + nonce);
Console.WriteLine("TimeStamp: " + timestamp);
Console.WriteLine("ConsumerKey: " + ConsumerKey);
Console.WriteLine("AppSecret: " + Secret);
//request url
StringBuilder b = new StringBuilder();
b.Append("http://www.flickr.com/services/oauth/request_token");
b.Append("?");
b.Append("oauth_nonce=");
b.Append(nonce);
b.Append("&oauth_timestamp=");
b.Append(timestamp);
b.Append("&oauth_consumer_key=");
b.Append(ConsumerKey);
b.Append("&oauth_callback=oob");
b.Append("&oauth_signature_method=HMAC-SHA1");
string requesturl = b.ToString();
Console.WriteLine("RequestUrl: " + requesturl);
//base url
string basestring;
StringBuilder bs = new StringBuilder();
bs.Append("GET&");
bs.Append(UrlHelper.Encode("http://www.flickr.com/services/oauth/request_token")+"&");
basestring = bs.ToString();
StringBuilder p = new StringBuilder();
p.Append("oauth_callback=oob");
p.Append("&oauth_consumer_key=");
p.Append(ConsumerKey);
p.Append("oauth_nonce=");
p.Append(nonce);
p.Append("&oauth_signature_method=HMAC-SHA1");
p.Append("&oauth_timestamp=");
p.Append(timestamp);
string paramers = UrlHelper.Encode(p.ToString());
basestring += paramers;
Console.WriteLine("Basestring: " + basestring);
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
string key = Secret + "&";
Console.WriteLine("Key: " + key);
byte[] keyByte = encoding.GetBytes(key);
//--create message to encrypt
byte[] messageBytes = encoding.GetBytes(basestring);
//--encrypt message using hmac-sha1 with the provided key
HMACSHA1 hmacsha1 = new HMACSHA1(keyByte);
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
//--signature
string signature = ByteToString(hashmessage);
Console.WriteLine("Signature: " + signature);
Console.WriteLine("Final Request: " + requesturl + "&oauth_signature=" + signature);
Console.ReadKey(true);
}
public static string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
}
When i browse to the url this applications give me, i get the following response:
oauth_problem=signature_invalid&debug_sbs=GET&http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Fwww.google.be%26oauth_consumer_key%3D1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a%26oauth_nonce%3D27504343%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1329469580
It seems that my signature for the request is invalid.
I hope someone can help me get the right signature for these requests.
I know there is a FlickNet Library that already did the hard work for most of the developers but i think it can be useful to get this working too. I looked into the source code of FlickrNet but didn't find the final peace to complete this code.
Let me know if you can help me. It would be so great!
Thanks!
Ok, I finally found the answer myself. Here are a few things you have to keep in mind when signing requests for oauth.
signature must be encrypted with HMAC-SHA1 using the basestring(see nr.2) as text to be encrypted and the clientsecret and the token_secret (if you have one) (see nr. 3)
basestring = [HttpMethod]&[FlickrAPIEndpoint]&[Parameters]
Key for request oauth_token = [ApiSecret]&
(or key = [ApiSecret]&[Oauth_token_secret] for request access_token)
IMPORTANT: FlickrAPIEndPoint and Parameters must be UrlEncoded (in two parts!)
I have used a separate class for the encoding because the HttpUtility.UrlEncode method uses lowercase encoding while the uppercase encoding should be used.
IMPORTANT: Parameters must be in alphabetical order!
Here's the code for a console application that will create a signed request for a request token and a request token secret.
class Program
{
private static string Secret = "9dcc18a121e9a02e";
private static string ConsumerKey = "3aafc63ec6b05f3f9a9ff3a1c35ce541";
private static string request_token = "";
static void Main(string[] args)
{
string requestString = "http://www.flickr.com/services/oauth/request_token";
//generate a random nonce and a timestamp
Random rand = new Random();
string nonce = rand.Next(999999).ToString();
string timestamp = GetTimestamp();
//create the parameter string in alphabetical order
string parameters = "oauth_callback=" + UrlHelper.Encode("http://www.example.com");
parameters += "&oauth_consumer_key=" + ConsumerKey;
parameters += "&oauth_nonce=" + nonce;
parameters += "&oauth_signature_method=HMAC-SHA1";
parameters += "&oauth_timestamp=" + timestamp;
parameters += "&oauth_version=1.0";
//generate a signature base on the current requeststring and parameters
string signature = generateSignature("GET", requestString, parameters);
//add the parameters and signature to the requeststring
string url = requestString + "?" + parameters + "&oauth_signature=" + signature;
//test the request
WebClient web = new WebClient();
string result = web.DownloadString(url);
Console.WriteLine("Flickr Response: ");
Console.WriteLine(result); //contains the oauth_token and the oauth_token_secret
Console.ReadKey(true);
}
private static string generateSignature(string httpMethod, string ApiEndpoint, string parameters)
{
//url encode the API endpoint and the parameters
//IMPORTANT NOTE:
//encoded text should contain uppercase characters: '=' => %3D !!! (not %3d )
//the HtmlUtility.UrlEncode creates lowercase encoded tags!
//Here I use a urlencode class by Ian Hopkins
string encodedUrl = UrlHelper.Encode(ApiEndpoint);
string encodedParameters = UrlHelper.Encode(parameters);
//generate the basestring
string basestring = httpMethod + "&" + encodedUrl + "&";
parameters = UrlHelper.Encode(parameters);
basestring = basestring + parameters;
//hmac-sha1 encryption:
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
//create key (request_token can be an empty string)
string key = Secret + "&" + request_token;
byte[] keyByte = encoding.GetBytes(key);
//create message to encrypt
byte[] messageBytes = encoding.GetBytes(basestring);
//encrypt message using hmac-sha1 with the provided key
HMACSHA1 hmacsha1 = new HMACSHA1(keyByte);
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
//signature is the base64 format for the genarated hmac-sha1 hash
string signature = System.Convert.ToBase64String(hashmessage);
//encode the signature to make it url safe and return the encoded url
return UrlHelper.Encode(signature);
}
//generator of unix epoch time
public static String GetTimestamp()
{
int epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
return epoch.ToString();
}
}
UrlHelper class by Ian Hopkins used for the url encoding
/// <summary>
/// URL encoding class. Note: use at your own risk.
/// Written by: Ian Hopkins (http://www.lucidhelix.com)
/// Date: 2008-Dec-23
/// (Ported to C# by t3rse (http://www.t3rse.com))
/// </summary>
public class UrlHelper
{
public static string Encode(string str)
{
var charClass = String.Format("0-9a-zA-Z{0}", Regex.Escape("-_.!~*'()"));
return Regex.Replace(str,
String.Format("[^{0}]", charClass),
new MatchEvaluator(EncodeEvaluator));
}
public static string EncodeEvaluator(Match match)
{
return (match.Value == " ") ? "+" : String.Format("%{0:X2}", Convert.ToInt32(match.Value[0]));
}
public static string DecodeEvaluator(Match match)
{
return Convert.ToChar(int.Parse(match.Value.Substring(1), System.Globalization.NumberStyles.HexNumber)).ToString();
}
public static string Decode(string str)
{
return Regex.Replace(str.Replace('+', ' '), "%[0-9a-zA-Z][0-9a-zA-Z]", new MatchEvaluator(DecodeEvaluator));
}
}
Are you writing this from scratch? If so, you shouldn't. Use http://flickrnet.codeplex.com/ instead. This library has already done the heavy lifting for you.

Categories

Resources