Azure auth: an example
i was able to put together a simple example of how to construct a valid authentication header for the Azure Table Storage service. it's a bit convoluted. i'm already on record saying i'm not a fan of this custom auth scheme. but since the folks at MSFT failed to check w/ me first[grin], we'll all have to learn to deal with it.
this solution does not rely on the Azure SDK. the advantage here is that anyone with an HTTP client and a hashing library can use this as a template to start manipulating their Azure storage accounts. no .NET requirements, not OS requirements. just HTTP.
below is the C# code that gets the list of tables in a storage account. to run this, you'll need access to the Azure Storage service. that means you need your project name, endpoint, and Azure primary key. once you plug them into this example, you can run this console app and get an Atom feed back that lists your tables.
using System; using System.Text; using System.Security.Cryptography; using System.Net; using System.IO; using System.Web; using System.Configuration; namespace Amundsen.Azure.Storage { class Program { static void Main(string[] args) { // args for this sample string keyType = "SharedKey"; string method = "GET"; string contentMD5 = string.Empty; string contentType = "application/atom+xml"; DateTime reqDate = DateTime.UtcNow; // formatters string fmtHeader = "{0} {1}:{2}"; string fmtStringToSign = "{0}\n{1}\n{2}\n{3:R}\n{4}"; // get data from config file string account = GetConfigItem("account"); // your azure project name string endPoint = GetConfigItem("endPoint"); // the table endpoint created for your azure project string authKey = GetConfigItem("authKey"); // the primary key created for your azure project // build request/resource strings string canonicalResource = string.Format("/{0}/{1}", account, "tables"); string requestUrl = string.Format("{0}/{1}", endPoint, "tables"); // build up auth hash string authValue = string.Format(fmtStringToSign, method, contentMD5, contentType, reqDate, canonicalResource); string sigValue = ComputeMacSha(authValue, Convert.FromBase64String(authKey)); string authHeader = string.Format(fmtHeader, keyType, account, sigValue); // make the request and show response try { string rtn = string.Empty; WebRequest req = WebRequest.Create(requestUrl); req.Headers.Add("x-ms-date", string.Format("{0:R}", reqDate)); req.Headers.Add("authorization", authHeader); req.ContentType = contentType; req.Method = method; WebResponse resp = req.GetResponse(); using (StreamReader sr = new StreamReader(resp.GetResponseStream(), true)) { rtn = sr.ReadToEnd(); sr.Close(); } resp.Close(); Console.WriteLine(rtn); } catch (WebException wex) { HttpWebResponse wrsp = (HttpWebResponse)wex.Response; Console.WriteLine(string.Format("{0} : {1}", wrsp.StatusCode,wrsp.StatusDescription)); } catch (HttpException hex) { Console.WriteLine(hex.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.ReadLine(); } // config reading helpers private static string GetConfigItem(string key) { return GetConfigItem(key, string.Empty); } private static string GetConfigItem(string key, string defaultValue) { return (ConfigurationSettings.AppSettings[key] != null ? ConfigurationSettings.AppSettings[key] : defaultValue); } // hashing helper private static string ComputeMacSha(string canonicalizedString, byte[] key) { byte[] dataToMAC = System.Text.Encoding.UTF8.GetBytes(canonicalizedString); using (HMACSHA256 hmacsha1 = new HMACSHA256(key)) { return System.Convert.ToBase64String(hmacsha1.ComputeHash(dataToMAC)); } } } }