{"id":847,"date":"2009-08-14T15:33:14","date_gmt":"2009-08-14T15:33:14","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=847"},"modified":"2009-08-14T15:38:15","modified_gmt":"2009-08-14T15:38:15","slug":"authenticating-with-an-oauth-1-0a-provider-from-net-cf","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=847","title":{"rendered":"Authenticating with an OAuth 1.0a provider from .NET CF"},"content":{"rendered":"<p><img decoding=\"async\" src=\"http:\/\/i267.photobucket.com\/albums\/ii311\/dale_lane\/090813-bladelocate-authverify.gif\" align=\"right\" vspace=\"10\" hspace=\"10\" style=\"border: thin solid black\"\/>Last night, I <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=831\">shared my first stab at a mobile Fire Eagle client<\/a>: a Windows Mobile application which posts location updates to the <a href=\"http:\/\/fireeagle.yahoo.net\/\" target=\"_blank\">Yahoo! Fire Eagle<\/a> service. <\/p>\n<p>A couple of the bits of code were fiddly, and are worth sharing. <\/p>\n<p>In this post, I&#8217;ll outline how I perform the code behind <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=831#oauth\">the OAuth authentication I described in my last post<\/a>. Hopefully, this might help anyone else wanting to do something similar.<br \/>\n<br clear=\"all\"\/><br \/>\n<!--more-->Before I start, a few quick warnings \/ comments:<\/p>\n<ul>\n<li>I needed to use .NET Compact Framework (.NET CF) &#8211; the subset of .NET that you get on Windows Mobile. In a few places, you might see my code doing something in a more long-winded way than might be necessary with the helper classes you get in the full .NET framework\n<\/li>\n<li>I used .NET 2 &#8211; this is what comes pre-installed on Windows Mobile 6, so it&#8217;s a big help to avoid getting users to have to install .NET 3 on their phone. Again, it means I&#8217;ve not taken advantage of some easier ways of doing things if I&#8217;d used .NET 3.5\n<\/li>\n<li>I was using Fire Eagle&#8217;s <a href=\"http:\/\/fireeagle.yahoo.net\/developer\/documentation\/mobile_auth\" target=\"_blank\">auth for mobile applications<\/a> so the code is based on that authentication sequence\n<\/li>\n<li>I needed to use HMACSHA1 to generate a signature &#8211; a class which is missing in the .NET Compact Framework. For my app, I used an implementation from the Community Edition of the (awesome!) <a href=\"http:\/\/opennetcf.com\/Products\/SmartDeviceFramework\/tabid\/65\/Default.aspx\" target=\"_blank\">Smart Device Framework<\/a> from <a href=\"http:\/\/opennetcf.com\/\" target=\"_blank\">OpenNetCF<\/a>. The API is consistent enough with .NET Standard Framework that if you are writing a desktop application, you can probably ignore this.\n<\/li>\n<li>Big thanks to the contributors of the <a href=\"http:\/\/code.google.com\/p\/oauth\/\" target=\"_blank\">oauth project<\/a> on Google Code. The <a href=\"http:\/\/code.google.com\/p\/oauth\/source\/browse\/code\/csharp\/OAuthBase.cs\" target=\"_blank\">csharp code<\/a> there isn&#8217;t compatible with .NET CF, and isn&#8217;t updated for OAuth 1.0a, so isn&#8217;t suitable for use as-is, but it was still a massive help in getting me started in understanding how to generate a valid signature. And I did nick a few generic bits from there (<em>In essence, of the code that follows, if it looks sane, I borrowed it from the <a href=\"http:\/\/code.google.com\/p\/oauth\/source\/browse\/code\/csharp\/OAuthBase.cs\" target=\"_blank\">reference implementation<\/a>. If it&#8217;s gibberish, I probably wrote it myself!<\/em>)\n<\/li>\n<li>This was my first attempt at writing an OAuth application client, so I&#8217;m not saying this is how you <strong>should<\/strong> do it&#8230; rather this is what I managed to get to work \ud83d\ude42\n<\/li>\n<li>In reality, the two methods below are quite similar, and in my app, I reused code in more generic methods. However, generic methods can make it harder to understand how specific operations work, so for this post I&#8217;ve expanded out methods so you can see exactly what you need to do to get an access token, for example. This is for readability&#8230; this isn&#8217;t meant to be code for an efficient library.<\/li>\n<li>I&#8217;ve ripped out the error handling to make the code easier to read in a blog post&#8230; but if you wanted to use this for real, you probably want to catch an exception or two \ud83d\ude09\n<\/li>\n<\/ul>\n<p>With that out of the way&#8230; here is the code. <\/p>\n<p>As mentioned above, I am following the authentication sequence from <a href=\"http:\/\/fireeagle.yahoo.net\/developer\/documentation\/mobile_auth\" target=\"_blank\">Fire Eagle&#8217;s mobile auth<\/a>. <\/p>\n<p>Step 1 from that page is <strong>Obtaining an unauthorized request token<\/strong><\/p>\n<pre style=\"overflow: scroll; font-size: 1.1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">\/* these are the values we want to get from Fire Eagle by the end of this *\/\r\nString requestToken  = \"\";\r\nString requestSecret = \"\";\r\n\r\n\/* for oauth_timestamp *\/\r\nTimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);\r\nstring timestamp = Convert.ToInt64(ts.TotalSeconds).ToString();\r\n\r\n\/* for oauth_nonce *\/\r\n\/* (obviously you wouldn't create a new Random class every time!) *\/\r\nstring nonce = new Random().Next(123400, 9999999).ToString();\r\n\r\n\/* parameters to include in the request - get the list from       *\/\r\n\/*  \"Obtaining an unauthorized request token\"                     *\/\r\n\/* http:\/\/fireeagle.yahoo.net\/developer\/documentation\/mobile_auth *\/\r\nSystem.Collections.Generic.List&lt;string&gt; parameters = new System.Collections.Generic.List&lt;string&gt;();\r\nparameters.Add(\"oauth_callback=oob\");\r\nparameters.Add(\"oauth_consumer_key=\" + UrlEncode(OAUTHCONSUMERKEY_FOR_MY_APP));\r\nparameters.Add(\"oauth_nonce=\" + UrlEncode(nonce));\r\nparameters.Add(\"oauth_timestamp=\" + UrlEncode(timestamp));\r\nparameters.Add(\"oauth_signature_method=HMAC-SHA1\");\r\nparameters.Add(\"oauth_version=1.0a\");\r\n\r\n\/* the url to get a request token *\/\r\nstring url = \"https:\/\/fireeagle.yahooapis.com\/oauth\/request_token\";\r\n\r\n\/* although not clearly documented, it seems that parameters need to be *\/\r\n\/*  sorted in order for Fire Eagle to accept the signature              *\/\r\nparameters.Sort();\r\nstring parametersStr = string.Join(\"&\", parameters.ToArray());\r\n\r\nstring baseStr = \"GET\" + \"&\" + \r\n                 UrlEncode(url) + \"&\" + \r\n                 UrlEncode(parametersStr);\r\n\r\n\/* create the crypto class we use to generate a signature for the request *\/\r\nHMACSHA1 sha1 = new HMACSHA1();\r\nbyte[] key = Encoding.UTF8.GetBytes(VAL_OAUTHCONSUMERSECRET + \"&\" + \r\n                                    requestSecret); \r\nif (key.Length &gt; 64)\r\n{\r\n    \/* I had to do this to handle a minor bug in my version of HMACSHA1 *\/\r\n    \/*  which falls over if you give it keys that are too long          *\/\r\n    \/* You probably won't need to do this.                              *\/\r\n    SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();\r\n    key = coreSha1.ComputeHash(key);\r\n}\r\nsha1.Key = key;\r\n\r\n\/* generate the signature and add it to our parameters *\/\r\nbyte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr);\r\nbyte[] baseStringHash = sha1.ComputeHash(baseStringBytes);\r\nString base64StringHash = Convert.ToBase64String(baseStringHash);\r\nString encBase64StringHash = UrlEncode(base64StringHash);\r\nparameters.Add(\"oauth_signature=\" + encBase64StringHash);\r\nparameters.Sort();\r\n\r\n\/* we are ready to send the request! *\/\r\nstring requestUrl = url + \"?\" + string.Join(\"&\", parameters.ToArray());\r\nHttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);\r\nrequest.Method = \"GET\";\r\nrequest.ContentType = \"application\/x-www-form-urlencoded\";\r\n\r\nstring rawData = \"\";\r\n\r\ntry\r\n{\r\n    HttpWebResponse response = (HttpWebResponse)request.GetResponse();\r\n    StreamReader responseStream = new StreamReader(response.GetResponseStream());\r\n    rawData = responseStream.ReadToEnd();\r\n    response.Close();\r\n}\r\ncatch (WebException err)\r\n{\r\n    Stream objStream = err.Response.GetResponseStream();\r\n    StreamReader objStreamReader = new StreamReader(objStream);\r\n    rawData = objStreamReader.ReadToEnd();\r\n}\r\n\r\n\/* if it worked, we should have oauth_token and   *\/\r\n\/*  oauth_token_secret in the response            *\/\r\nforeach (string pair in rawData.Split(new char[] { '&' }))\r\n{\r\n    string[] split_pair = pair.Split(new char[] { '=' });\r\n\r\n    switch (split_pair[0])\r\n    {\r\n        case \"oauth_token\":\r\n            requestToken = split_pair[1];\r\n            break;\r\n        case \"oauth_token_secret\":\r\n            requestSecret = split_pair[1];\r\n            break;\r\n    }\r\n}<\/pre>\n<p>This gives you <code>requestToken<\/code> and <code>requestSecret<\/code>. <\/p>\n<p>Step 2 is <strong>Obtaining user authorizations<\/strong><\/p>\n<p>You give the user <code>requestToken<\/code> and send them to <code>https:\/\/fireeagle.yahoo.net\/oauth\/mobile_auth\/MY_APP_ID<\/code>. <\/p>\n<p>They enter the request token into the webpage, and hit confirm. This gets them a verification code which they bring back to your application.<\/p>\n<p>You can see screenshots of this in <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=831#oauth\">my last post<\/a>.<\/p>\n<p>Step 3 is <strong>Obtaining user-specific access token<\/strong><\/p>\n<p>This is very similar to getting a request token. <\/p>\n<pre style=\"overflow: scroll; font-size: 1.1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">\/* these are the values we got from Fire Eagle in step 1 *\/\r\nString requestToken  = \"\";\r\nString requestSecret = \"\";\r\n\r\n\/* this is the value the user got from Fire Eagle website in step 2 *\/\r\nString verifier      = \"SOMETHING\"; \r\n\r\n\/* these are the values we want to get from Fire Eagle *\/\r\nString accessToken   = \"\";\r\nString accessSecret  = \"\";\r\n\r\n\/* for oauth_timestamp *\/\r\nTimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);\r\nstring timestamp = Convert.ToInt64(ts.TotalSeconds).ToString();\r\n\r\n\/* for oauth_nonce *\/\r\n\/* (obviously you wouldn't create a new Random class every time!) *\/\r\nstring nonce = new Random().Next(100000, 9999999).ToString();\r\n\r\n\/* parameters to include in the request - get the list from       *\/\r\n\/*  \"Obtaining user-specific access token\"                        *\/\r\n\/* http:\/\/fireeagle.yahoo.net\/developer\/documentation\/mobile_auth *\/\r\nSystem.Collections.Generic.List&lt;string&gt; parameters = new System.Collections.Generic.List&lt;string&gt;();\r\nparameters.Add(\"oauth_consumer_key=\" + UrlEncode(OAUTHCONSUMERKEY_FOR_MY_APP));\r\nparameters.Add(\"oauth_verifier=\" + verifier);\r\nparameters.Add(\"oauth_token=\" + UrlEncode(requestToken));\r\nparameters.Add(\"oauth_nonce=\" + UrlEncode(nonce));\r\nparameters.Add(\"oauth_timestamp=\" + UrlEncode(timestamp));\r\nparameters.Add(\"oauth_signature_method=HMAC-SHA1\");\r\nparameters.Add(\"oauth_version=1.0a\");\r\n\r\n\/* the url to get an access token *\/\r\nstring url = \"https:\/\/fireeagle.yahooapis.com\/oauth\/access_token\";\r\n\r\n\/* although not clearly documented, it seems that parameters need to be *\/\r\n\/*  sorted in order for Fire Eagle to accept the signature              *\/\r\nparameters.Sort();\r\nstring parametersStr = string.Join(\"&\", parameters.ToArray());\r\n\r\nstring baseStr = \"GET\" + \"&\" + \r\n                 UrlEncode(url) + \"&\" + \r\n                 UrlEncode(parametersStr);\r\n\r\n\/* create the crypto class we use to generate a signature for the request *\/\r\nHMACSHA1 sha1 = new HMACSHA1();\r\nbyte[] key = Encoding.UTF8.GetBytes(VAL_OAUTHCONSUMERSECRET + \"&\" + \r\n                                    requestSecret); \r\nif (key.Length &gt; 64)\r\n{\r\n    \/* I had to do this to handle a minor bug in my version of HMACSHA1 *\/\r\n    \/*  which falls over if you give it keys that are too long          *\/\r\n    \/* You probably won't need to do this.                              *\/\r\n    SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();\r\n    key = coreSha1.ComputeHash(key);\r\n}\r\nsha1.Key = key;\r\n\r\n\/* generate the signature and add it to our parameters *\/\r\nbyte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr);\r\nbyte[] baseStringHash = sha1.ComputeHash(baseStringBytes);\r\nString base64StringHash = Convert.ToBase64String(baseStringHash);\r\nString encBase64StringHash = UrlEncode(base64StringHash);\r\nparameters.Add(\"oauth_signature=\" + encBase64StringHash);\r\nparameters.Sort();\r\n\r\n\/* we are ready to send the request! *\/\r\nstring requestUrl = url + \"?\" + string.Join(\"&\", parameters.ToArray());\r\nHttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);\r\nrequest.Method = \"GET\";\r\nrequest.ContentType = \"application\/x-www-form-urlencoded\";\r\n\r\nstring rawData = \"\";\r\n\r\ntry\r\n{\r\n    HttpWebResponse response = (HttpWebResponse)request.GetResponse();\r\n    StreamReader responseStream = new StreamReader(response.GetResponseStream());\r\n    rawData = responseStream.ReadToEnd();\r\n    response.Close();\r\n}\r\ncatch (WebException err)\r\n{\r\n    Stream objStream = err.Response.GetResponseStream();\r\n    StreamReader objStreamReader = new StreamReader(objStream);\r\n    rawData = objStreamReader.ReadToEnd();\r\n}\r\n\r\n\/* if it worked, we should have oauth_token and   *\/\r\n\/*  oauth_token_secret in the response            *\/\r\nforeach (string pair in rawData.Split(new char[] { '&' }))\r\n{\r\n    string[] split_pair = pair.Split(new char[] { '=' });\r\n\r\n    switch (split_pair[0])\r\n    {\r\n        case \"oauth_token\":\r\n            accessToken = split_pair[1];\r\n            break;\r\n        case \"oauth_token_secret\":\r\n            accessSecret = split_pair[1];\r\n            break;\r\n    }\r\n}<\/pre>\n<p>Job done &#8211; the user has authenticated your app. <\/p>\n<p>Make sure that you put <code>accessToken<\/code> and <code>accessSecret<\/code> somewhere safe, to use these when you make API calls in future. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last night, I shared my first stab at a mobile Fire Eagle client: a Windows Mobile application which posts location updates to the Yahoo! Fire Eagle service. A couple of the bits of code were fiddly, and are worth sharing. In this post, I&#8217;ll outline how I perform the code behind the OAuth authentication I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-847","post","type-post","status-publish","format-standard","hentry","category-code"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/847","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=847"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/847\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=847"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=847"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=847"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}