Extending HttpClient with OAuth to Access Twitter

Many popular Web APIs such as the twitter API use some form of OAuth for authentication. HttpClient does not have baked in support for OAuth but using the HttpClient extensibility model you can add OAuth as part of the HttpMessageHandler pipeline.

The HttpMessageHandler pipeline is the main extensibility point for the HTTP object model underlying both HttpClient and ASP.NET Web API (they use the exact same model). The pipeline allows up to insert message handlers that can inspect, modify, and process HTTP requests and responses as they pass by. The following diagram shows where HttpMessageHandlers sit in the message path on both client (HttpClient) and server side (ASP.NET Web API). The work like “Russian Dolls” in that each handler passes the request to an inner handler until it hits the network or is short-circuited":

HttpMessageHandlers

Note that there is absolutely no requirement that you have to use the HttpClient with ASP.NET Web API – it is just to show that the model is symmetric on client and server side.

Our OAuth handler is very simple – it uses the a sample from OAuth.Net provided by Eran Sandler to do the actual OAuth signing.

Please see List of ASP.NET Web API and HttpClient Samples for the complete sample solution.

Getting a Twitter API Key

The first step is to sign in at the twitter developer site and create an app. That will give you necessary information for performing the OAuth authentication:

  • Consumer Key and Consumer Secret: identifies your application
  • Access Token and Access Token Secret: identifies the account your application is acting on behalf of

Once you have these values then you can continue with the sample.

Creating a HttpMessageHandler

First we create the OAuth HttpMessageHandler like this. The OAuthBase class is the OAuth signature generator from Eran Sandler mentioned above. Every time a request is submitted it hits the SendAsync method where we get the information from the request and update it with an appropriate OAuth authentication header before sending it on its way to the next handler.

    1: /// <summary>
    2: /// Basic DelegatingHandler that creates an OAuth authorization header based on the OAuthBase
    3: /// class downloaded from https://oauth.net
    4: /// </summary>
    5: public class OAuthMessageHandler : DelegatingHandler
    6: {
    7:     // Obtain these values by creating a Twitter app at https://dev.twitter.com/
    8:     private static string _consumerKey = "Enter your consumer key";
    9:     private static string _consumerSecret = "Enter your consumer secret";
   10:     private static string _token = "Enter your token";
   11:     private static string _tokenSecret = "Enter your token secret";
   12:  
   13:     private OAuthBase _oAuthBase = new OAuthBase();
   14:  
   15:     public OAuthMessageHandler(HttpMessageHandler innerHandler)
   16:         : base(innerHandler)
   17:     {
   18:     }
   19:  
   20:     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   21:     {
   22:         // Compute OAuth header 
   23:         string normalizedUri;
   24:         string normalizedParameters;
   25:         string authHeader;
   26:  
   27:         string signature = _oAuthBase.GenerateSignature(
   28:             request.RequestUri,
   29:             _consumerKey,
   30:             _consumerSecret,
   31:             _token,
   32:             _tokenSecret,
   33:             request.Method.Method,
   34:             _oAuthBase.GenerateTimeStamp(),
   35:             _oAuthBase.GenerateNonce(),
   36:             out normalizedUri,
   37:             out normalizedParameters,
   38:             out authHeader);
   39:  
   40:         request.Headers.Authorization = new AuthenticationHeaderValue("OAuth", authHeader);
   41:         return base.SendAsync(request, cancellationToken);
   42:     }
   43: }

The way this is wired up to an HttpClient is by using the HttpClient constructor that takes a HttpMessagHandler:

    1: // Create client and insert an OAuth message handler in the message path that 
    2: // inserts an OAuth authentication header in the request
    3: HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));

The HttpClientHandler is the default “network” handler provided by HttpClient that actually sends the request and received the response from the network.

Creating a Twitter Client

The only thing left is now to create the program submitting a request to twitter and handling the response. We use JsonValue to parse the data returned by twitter when accessing the latest entries posted by Scott Guthrie. When you submit the request, the request will hit the OAuth message handler and then make its way to the network.

    1: /// <summary>
    2: /// Sample illustrating how to write a simple twitter client using HttpClient. The sample uses a 
    3: /// HttpMessageHandler to insert the appropriate OAuth authentication information into the outgoing
    4: /// HttpRequestMessage. The result from twitter is read using JsonValue.
    5: /// </summary>
    6: class Program
    7: {
    8:     static string _address = "https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=scottgu&count=5";
    9:  
   10:     static void Main(string[] args)
   11:     {
   12:         // Create client and insert an OAuth message handler in the message path that 
   13:         // inserts an OAuth authentication header in the request
   14:         HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));
   15:  
   16:         // Send asynchronous request to twitter
   17:         client.GetAsync(_address).ContinueWith(
   18:             (requestTask) =>
   19:             {
   20:                 // Get HTTP response from completed task.
   21:                 HttpResponseMessage response = requestTask.Result;
   22:  
   23:                 // Check that response was successful or throw exception
   24:                 response.EnsureSuccessStatusCode();
   25:  
   26:                 // Read response asynchronously as JsonValue and write out tweet texts
   27:                 response.Content.ReadAsAsync<JsonArray>().ContinueWith(
   28:                     (readTask) =>
   29:                     {
   30:                         JsonArray statuses = readTask.Result;
   31:                         Console.WriteLine("\nLast 5 statuses from ScottGu's twitter account:\n");
   32:                         foreach (var status in statuses)
   33:                         {
   34:                             Console.WriteLine(status["text"] + "\n");
   35:                         }
   36:                     });
   37:             });
   38:  
   39:         Console.WriteLine("Hit ENTER to exit...");
   40:         Console.ReadLine();
   41:     }
   42: }

The output when running this sample should be 5 tweets written to the console.

Have fun!

Henrik

del.icio.us Tags: asp.net,webapi,mvc,web,rest,httpclient