Using WinRT’s WebAuthenticationBroker with Flickr’s OAuth API

Part 1: Get a Request Token

For one of my first apps at Microsoft, I decided to build a Windows Store App that would exchange data via Flickr’s APIs. One of the challenges I faced while developing this App was communicating with Flickr’s APIs that require authentication via OAuth protocol. WinRT’s WebAuthenticationBroker API helped me in facilitating the authentication process between the App and Flickr’s OAuth service. For more information on how WebAuthenticationBroker works, please refer this article on MSDN. The OAuth authentication flow is explained in 3 three steps on the Flickr’s website:

  1. Get a Request Token
  2. Get the User's Authorization
  3. Exchange the Request Token for an Access Token

I have divided this article in 2 parts based on the above authentication flow. In the first part, I’ll discuss the first step in the OAuth 1.0 authentication flow. In the second part, I’ll discuss the remaining two steps of authentication flow. Towards the end of the second part, I’ll also discuss about saving the token associated with the user to maintain their authentication status the next time they launch the App. Overall in the two parts, I have demonstrated the usage of WebAuthenticationBroker against Flickr’s OAuth service in a sample Windows Store App for Windows 8.

1. Get a Request Token

A user can be prompted for authentication at various points in an app like file upload, writing comments for a photo, tagging a photo etc. In my App, I use WebAuthenticationBroker in a scenario in which the user hits the login button in the sample Flickr App.

   When users hit the Login button in the sample App, they are navigated to the following screen: 

image

Figure 2: Login page displayed in a App container

Before we proceed to the next step of entering the credentials in the login page, let’s analyze what happened behind the scenes.

In the event handler for the Login button, a call was made to WebAuthenticationBroker’s AuthenticateAsync method. The AuthenticateAsync method renders the login screen in the App container by using the Flickr’s OAuth service. The method accepts three arguments i.e. options, requestUri, callbackUri. I have set options to WebAuthenticationOptions.None and callbackUri to the value returned from WebAuthenticationBroker.GetCurrentApplicationCallbackUri().But I need to pass a requestUri too.

A requestUri is the URL that loads the Login page for user and is the second step in the OAuth flow. A requestUri should be something similar to this: “https://secure.flickr.com/services/oauth/authorize?oauth_token=72157626737672178-022bbd2f4c2f3432&perms=write”. The value of oauth_token mentioned as part of the query string is the value of the Request token received from Flickr.

That means that before we can call WebAuthenticationBroker’s AuthenticateAsync method we need to first get a Request token from the Flickr OAuth API.

A Request token is a temporary token that will be used to authenticate the user to the application using the API key. In the third step of the OAuth flow, you will see that the Request token will be exchanged for an Access token.

To retrieve the Request token Flickr expects the request URL to be similar to this:

https://secure.flickr.com/services/oauth/request\_token ?oauth_nonce=95613465 &oauth_timestamp=1305586162 &oauth_consumer_key=653e7a6ecc1d528c516cc8f92cf98611 &oauth_signature_method=HMAC-SHA1 &oauth_version=1.0 &oauth_signature=7w18YS2bONDPL%2FzgyzP5XTr5af4%3D &oauth_callback=http%3A%2F%2Fwww.example.com

Figure 3: Sample signed URL for Request token

The above URL’s query string can be characterized as having some basic parameters (name – value pairs) and a signature parameter. The basic parameters are used for constructing the signature. To know more in detail on this topic, please refer this article’s ‘Signing Requests’ section.

In this article, I will briefly go over the steps but will definitely touch the coding part of it. To generate the Request token URL (Figure 3), I follow these steps:

a. Generate basic parameters for Flickr OAuth API

I need to first generate basic parameters for the Request token’s http request. With reference to theFlickrOAuth API, this is how they expect the basic parameters to look like:

oauth_nonce=89601180
oauth_timestamp=1305583298
oauth_consumer_key=653e7a6ecc1d528c516cc8f92cf98611
oauth_signature_method=HMAC-SHA1
oauth_version=1.0
oauth_callback=http%3A%2F%2Fwww.example.com

 

The below function creates a dictionary of basic parameters as per the above parameters :

C#

public static Dictionary<string,string> GetOAuthParameters(string apikey, string callbackUrl)
        {
            Random random = new Random();
            DateTime epochDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            TimeSpan timespan = DateTime.UtcNow - epochDate;
            string oauthTimestamp = timespan.TotalSeconds.ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
            string oauthNonce = random.Next(1000).ToString();
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("oauth_nonce", oauthNonce);
            parameters.Add("oauth_timestamp", oauthTimestamp);
            parameters.Add("oauth_consumer_key", apikey);
            parameters.Add("oauth_signature_method", "HMAC-SHA1");
            parameters.Add("oauth_version", "1.0");
            parameters.Add("oauth_callback", callbackUrl);
            return parameters;
        }

Figure 4: Get basic parameters

Note:

  • The redirect URL or callback URL used in all the places has been set to the string returned from WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString().
  • The variable “apikey” is set to the value of the API key that you receive when you register for an app on the Flickr website.
b. Calculate signed URL

Once I have the basic parameters, I need to sort them and create a base string in the form of:

GET&https%3A%2F%2Fsecure.flickr.com%2Fservices%2Foauth%2Frequest_token&oauth_callback%3Dms-app%253A%252F%252Fs-1-15-2-452505077-3210332440-309548214-3674837716-3057654506-2702161574-51733630%252F%26oauth_consumer_key%3Dsdsdsdsdsdsdwdwdw%26oauth_nonce%3D246%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1348034567.41827%26oauth_version%3D1.0

Using the base string as the ‘text’ and the consumer secret key as the ‘key’, we then need to calculate the signature using HMAC-SHA1 encryption. The consumer secret key is one of the keys that you receive when you register for an App on the Flickr website.

The next thing would be to put together the base URL for Request token (https://secure.flickr.com/services/oauth/request_token), basic parameters and signature to generate a signed Request token URL as shown in Figure 3.

The method below helps me achieve that. I provide the basic parameters, Request Token base URL, secret key, and the bool parameter as ‘false’ to the method. And it returns the signed URL for obtaining Request token that is ready to be sent to the Flickr’s API. I would also use the below (CalculateOAuthSignedUrl()) method in the exchange of Request token for Access token step. That’s where I would call the method with the ‘exchangeStep’ parameter as ‘true’.

 

C#

public static string CalculateOAuthSignedUrl(Dictionary<string,string> parameters, string url, string secretKey, bool exchangeStep)
        {
            StringBuilder baseString = new StringBuilder();
            string baseStringForSig;
            SortedDictionary<string, string> sortedParams =  new SortedDictionary<string,string>();
            IBuffer keyMaterial;

            foreach (var param in parameters)
            {
                sortedParams.Add(param.Key, param.Value);
            }

            foreach (var param in sortedParams)
            {
                baseString.Append(param.Key);
                baseString.Append("=");
                baseString.Append(Uri.EscapeDataString(param.Value));
                baseString.Append("&");
            }
           
            //removing the extra ampersand
            baseString.Remove(baseString.Length - 1, 1);
            baseStringForSig = "GET&" + Uri.EscapeDataString(url) + "&" + Uri.EscapeDataString(baseString.ToString());

            //calculating the signature
            MacAlgorithmProvider HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");

            if (exchangeStep)
            {
                keyMaterial = CryptographicBuffer.ConvertStringToBinary(secretKey + "&" + OAuth_token_secret, BinaryStringEncoding.Utf8);
            }
            else
            {
                keyMaterial = CryptographicBuffer.ConvertStringToBinary(secretKey + "&", BinaryStringEncoding.Utf8);
            }

            CryptographicKey cryptoKey = HmacSha1Provider.CreateKey(keyMaterial);
            IBuffer dataString = CryptographicBuffer.ConvertStringToBinary(baseStringForSig, BinaryStringEncoding.Utf8);

            return url + "?" + baseString.ToString() + "&oauth_signature=" +
                Uri.EscapeDataString(CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Sign(cryptoKey, dataString)));
        }

Figure 5: Calculate signed URL

c. Send the signed URL and get the response

Once we have the signed URL for obtaining Request token, we are ready to send it the Flickr OAuth API. I use the method below for exchanging request/response from the Flickr’s API:

C#

public async static Task<string> GetResponseFromWeb(string url)
        {
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(url);
            string httpResponse = null;
            Request.Method = "GET";
            HttpWebResponse response = (HttpWebResponse)await Request.GetResponseAsync();
            if (response != null)
            {
                StreamReader data = new StreamReader(response.GetResponseStream());
                httpResponse = await data.ReadToEndAsync();
            }
            return httpResponse;
        }

Figure 6: Get http response from web

d. Parse the http response and extract the Request token

Flickr returns a response similar to the one below:

oauth_callback_confirmed=true &oauth_token=72157626737672178-022bbd2f4c2f3432 &oauth_token_secret=fccb68c4e6103197

I parse the response and extract the Request token:

public static void SetRequestToken(string response)
        {
            string [] keyValPairs = response.Split('&');
            for (int i = 0; i < keyValPairs.Length; i++)
            {
                String[] splits = keyValPairs[i].Split('=');
                switch(splits[0])
                {
                    case "oauth_token":
                        {
                            OAuth_token = splits[1];
                            break;
                        }
                    case "oauth_token_secret":
                        {
                            OAuth_token_secret = splits[1];
                        break;
                        }
                }
            }
        }

In the part 2 of this article, I will use the Request token extracted above for step 2 & 3 of the OAuth flow i.e. for user authorization purposes and eventually exchanging the Request token with Access token.