OAuth: Getting Started with OAuth in C#, .NET

I have been playing around with Pownce and their API. They offer HTTP Basic Authentication and OAuth authentication. I decided to give a go with OAuth since BASIC auth just seems, dirty insecure to me. I started digging around, and http://oauth.net/ has some good info. Under code there is a C# (CSharp) version – http://oauth.googlecode.com/svn/code/csharp/  but, I couldn’t find any good examples of getting started implementing this in your app, so…

I downloaded the OAuthBase.cs class and added it to a sample project so I could get going. Now, how to use this OAuth thing…

Well, first you need a “request token” server/url that you can use, something that takes your request and gives back a token (You can use http://term.ie/oauth/example/ to test, instead of Pownce  or some other utility)

As the “consumer” of the service, you have a key and a secret. The hardest part of the OAuth request is generating the signature, which the OAuthBase.cs does for you. I did run into some small issue with generating a timestamp though, seems that the OAuthBase.cs class had/has a bug in the timestamp function. it was returning back a timestamp like 12393923423.134  instead of just 12393923423 – which the first one, with the .134 will cause an invalid signature in your requests.

I sent a comment/message to the creator of OAuthBase.cs about it, not sure what else to do there, I am pretty sure I had the latest version (it was linked off oauth.net)

here is the function I changed:

public virtual string GenerateTimeStamp() {
    // Default implementation of UNIX time of the current UTC time
    TimeSpan ts = DateTime.UtcNow – new DateTime(1970, 1, 1, 0, 0, 0, 0);
    string timeStamp = ts.TotalSeconds.ToString();
    timeStamp = timeStamp.Substring(0, timeStamp.IndexOf(“.”));
    return timeStamp;           
}

Now, you want to test this out, create a test .NET app (C#), and add OAuthBase.cs to your project. I created a test Windows Form app. I had to add a reference to System.Web as well., then the basic code (I am using the test OAuth server)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using OAuth;

namespace PownceTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            string consumerKey = “key”;
            string consumerSecret = “secret”;
            Uri uri = new Uri(“http://term.ie/oauth/example/request_token.php”);

            OAuthBase oAuth = new OAuthBase();
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string sig = oAuth.GenerateSignature(uri,
                consumerKey, consumerSecret, 
                string.Empty, string.Empty,
                “GET”, timeStamp, nonce,
                OAuthBase.SignatureTypes.HMACSHA1);

            sig = HttpUtility.UrlEncode(sig);

            StringBuilder sb = new StringBuilder(uri.ToString());
            sb.AppendFormat(“?oauth_consumer_key={0}&”, consumerKey);
            sb.AppendFormat(“oauth_nonce={0}&”, nonce);
            sb.AppendFormat(“oauth_timestamp={0}&”, timeStamp);
            sb.AppendFormat(“oauth_signature_method={0}&”, “HMAC-SHA1″);
            sb.AppendFormat(“oauth_version={0}&”, “1.0”);
            sb.AppendFormat(“oauth_signature={0}”, sig);

            System.Diagnostics.Debug.WriteLine(sb.ToString());

        }
    }
}

 

If you run that app, you will get a debug line like..

http://term.ie/oauth/example/request_token.php?oauth_consumer_key=key&oauth_nonce=1901809&oauth_timestamp=1208645244&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=iv%2b45QPR9a%2fMDjw8qkEee61Fp0g%3d

One thing that had me scratching my head of a second was my signature was good like 80% of the time, I noticed I wasn’t URLEncoding it, so spaces were getting sent as ( ) instead of (+) – doh!

If you click on the link that is generated, you will get a response like

oauth_token=requestkey&oauth_token_secret=requestsecret

We are good to go! This is just the first step. We need to use those tokens now to move on, but we got past the first step of authenticating to the OAuth server to get tokens! Yay! (Ex: your app has to actually request that url, use the tokens, have the user authorize your app, then go from there..)

This maybe the first in a few blog posts on OAuth – happy coding!

About these ads

30 thoughts on “OAuth: Getting Started with OAuth in C#, .NET”

  1. Hi Steve,
    its great article you have provide and save us with a mess thanx for that.
    I m getting problem in getting Request token from netflix.The Link I generated is

    http://api.netflix.com/oauth/request_token?oauth_consumer_key=kwznqsw3kcwdgs6hdyepabzb&oauth_nonce=1583318&oauth_timestamp=1227769198&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=Ynxk44w6Wpk%2b97LPKj5N2CZW8Oc%3d

    but it is returning me invalid signature

    m i wrong somewhere ?is there a particular sequence of passing parameters please help me.

    Thanx

    pawan bali

    Like

  2. instead of using .Substring(…) in a GenerateTimeStamp function use this:

    return Convert.ToInt64(ts.TotalSeconds).ToString(System.Globalization.CultureInfo.InvariantCulture);

    Like

  3. Hey CTSBellevue,
    if you’re getting an invalid signature method try going into the OAuthBase.cs file and in the “GenerateSignature” method on the line #278 wrap the “consumerKey” value with “UrlEncode” so it will look something like this: string signatureBase = GenerateSignatureBase(url, UrlEncode(consumerKey), token, …..

    Hope that helps!
    greenerist

    Like

  4. Hey there,

    Thanks for the article. Even though the oAuthBase.cs has been updated, this article helped me out greatly. I wanted to share something that worked for me. I noticed that my request calls were working about 80% of the time but were failing when the character “+” was in the querystring of the sig. In any case, I increased my performance up to 100% by doing a simple replace in the GenerateSignature method.

    In my file, at line 325 I updated the line to include a .replace on it:

    return GenerateSignatureUsingHash(signatureBase, hmacsha1).Replace(“+”, “%2B”);

    the %2B was off some url unicode paramaters table I found that is another way of relating a +.

    Please email me if a better way is found of replicating this functionality.

    Like

  5. Will this run on vs.net 2005/ .net 2.0. Trying this exact code in a Page_load but getting syntax error:

    No overload for method ‘GenerateSignature’ takes ‘9’ arguments

    all I changed in your code was the consumer key, the consumerSecret and the Uri.

    this line is the same:
    string sig = oAuth.GenerateSignature(uri,consumerKey, consumerSecret,string.Empty, string.Empty,”GET”, timeStamp, nonce,OAuthBase.SignatureTypes.HMACSHA1);

    Like

    1. I am having the same problem, Can any one tell us what are the suitable values for argument 9 and 10? function/method required 10 args and in above sample code only 9 are given.

      Like

      1. change the line :
        string sig = oAuth.GenerateSignature(uri,
        consumerKey, consumerSecret,
        string.Empty, string.Empty,string.Empty,string.Empty,
        “GET”,timeStamp, nonce,
        OAuthBase.SignatureTypes.HMACSHA1, out outUrl,
        out queryString);

        Like

      2. Error 1 The name ‘outUrl’ does not exist in the current context D:OkaytestDefault.aspx.cs 31 68 D:Okaytest
        Error 2 The name ‘queryString’ does not exist in the current context D:OkaytestDefault.aspx.cs 32 33 D:Okaytest

        Like

    1. I am struck here. Even I want post tweets into twitter using this through either web application or windows. Pl let me know how you have achieved by using the above code?

      Like

  6. The ony hard thing in oauth is the signature. I use this in http://coulisse.luvdasun.com

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Collections.Specialized;
    using System.Security.Cryptography;

    namespace LuvDaSun.OAuth
    {
    public static class OAuthUtil
    {
    static Encoding _encoding = Encoding.ASCII;
    static char[] _unreservedChars = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~”.ToCharArray();
    //http://tools.ietf.org/html/rfc5849#section-3.6
    public static string UrlEncode(string str)
    {
    var sb = new StringBuilder();
    foreach (var ch in str)
    {
    if (_unreservedChars.Contains(ch)) sb.Append(ch);
    else sb.Append(Uri.HexEscape(ch));
    }
    return sb.ToString();
    }

    //http://tools.ietf.org/html/rfc5849#section-3.4.1.2
    public static string UrlBase(Uri url)
    {
    return Uri.EscapeUriString(new Uri(url, url.AbsolutePath).ToString());
    }

    //http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
    public static string NormalizeParameters(NameValueCollection parameters)
    {
    return string.Join(“&”, parameters.AllKeys
    .SelectMany(k => parameters.GetValues(k)
    .Select(v => string.Format(“{0}={1}”, UrlEncode(k), UrlEncode(v)))
    )
    .OrderBy(kv => kv)
    .ToArray()
    );
    }

    //http://tools.ietf.org/html/rfc5849#section-3.4.2
    public static string Signature(string method, Uri url, string clientSecret, string tokenSecret, NameValueCollection parameters)
    {
    string key = string.Format(“{0}”
    , UrlEncode(clientSecret)
    , UrlEncode(tokenSecret)
    );
    string text = string.Format(“{0}”
    , UrlEncode(method.ToUpperInvariant())
    , UrlEncode(UrlBase(url))
    , UrlEncode(NormalizeParameters(parameters))
    );
    string digest;

    using (var alg = new HMACSHA1())
    {
    alg.Key = _encoding.GetBytes(key);
    alg.ComputeHash(_encoding.GetBytes(text));
    digest = Convert.ToBase64String(alg.Hash);
    }

    return digest;
    }

    }
    }

    Like

  7. I found what I believe to be an oversight in OAuthBase. This was made aparent when trying to integrate with google and having the required scope parameter. This parameter contains reserved chars and these need escaping before merging. The result is that these chars end up double escaped in the signature base string.

    Thanks to: http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/ for the step by step onthis.

    I Was having invalid signature errors when the scope var contains http://

    I added this just after the “normalizedUrl += url.AbsolutePath” approx line 266

    //Url Encode any parameters that may contain reserved characters
    foreach (QueryParameter parameter in parameters)
    {
    parameter.Value = this.UrlEncode(parameter.Value);
    }

    and changed the QueryParameter Properties to accept a set.

    This solved my problem and my signatures are now valid.

    Like

  8. Nice article. You may also try SocialAuth.NET (http://code.google.com/p/socialauth-net/) This library allows you to authenticate with Yahoo, Google, MSN and Facebook. What makes it different is that you do not need to worry about signature, token, parties etc. Just Call method like Login(“Facebook”). Thats it! This component takes care of rest of the process. Also, it allows you to access profile and friends list with methods like GetContacts() and GetProfile()

    Like

  9. Hi,
    Please help me to Migrate Google Apps Marketplace V1 to V2.
    As specified in https://developers.google.com/apps-marketplace/v1migratev2 i’m using the same API
    String url = String.Format(“https://www.googleapis.com/appsmarket/v2/upgradableApp/{0}/{1}/{2}”, oldAppId, chromeListing, domain);
    but all time it returns error.
    Please help to Migrate.

    Code I’m using is….

    String result = “”;
    String url = String.Format(“https://www.googleapis.com/appsmarket/v2/upgradableApp/{0}/{1}/{2}”, oldAppId, chromeListing, domain);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = “PUT”;
    request.ContentType = “application/json”;
    request.Accept = “application/json”;
    request.ProtocolVersion = HttpVersion.Version11;
    request.Credentials = CredentialCache.DefaultCredentials;
    //request.Headers.Add(“Authorization”, “Bearer:ya29.ZgARsBgnABHMj08AAAD1lh0Wg86bTeDZjodrSXbW-M0srk-Kl5im2xaetwzHTYkCWxGChsoyLo6U4Ffar33qWhCBPlgRTBfwjCNOX2tlPWVegZUjIc27H1gTGiZ-IA”);
    request.Headers.Add(“Authorization”, “oAuth 1.0″);
    Hashtable postObj = new Hashtable();
    //postObj[“Authorization”] = “oAuth”;
    postObj[“oauth_VERSION”] = “1.0”;
    postObj[“oauth_Consumer_Key”] = UrlEncodeForGoogle(oldClientId);
    postObj[“oauth_Consumer Key Secret”] = oldSecret;
    postObj[“oauth_TIMESTAMP”] = timestamp();
    postObj[“oauth_NONCE”] = Nonce();
    //postObj[“oauth_SIGN_METHOD”] = “HMACSHA1″;
    String s1 = new JavaScriptSerializer().Serialize(postObj);
    var bs = Encoding.UTF8.GetBytes(s1);
    using (Stream reqStream = request.GetRequestStream())
    {
    reqStream.Write(bs, 0, bs.Length);
    }
    using (WebResponse response = request.GetResponse())
    {
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
    result = sr.ReadToEnd();
    sr.Close();
    }
    }

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s