DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone >

Developing SevenDrops - A Dropbox-based photo uploader for Windows Phone 7 [4/6]

Denzel D. user avatar by
Denzel D.
·
Apr. 05, 11 · · Interview
Like (0)
Save
Tweet
8.35K Views

Join the DZone community and get the full member experience.

Join For Free

Time to get further with OAuth, and now it gets a little bit more complicated because we'll have to deal with request signing (which might be a headache for some beginners). As I showed in my previous article, we already have the token and the secret needed to perform the required manipulations.

I try to generally avoid parameter-based OAuth flow, so I will be building an OAuth header. The first method I am going to perform experiments is the one that retrieves profile information and it is represented by the following endpoint:

https://api.dropbox.com/<version>/account/info

Where once again, the version is currently is set to 0 but is subject to change at any time the Dropbox system gets an update.

Let's look at the set of parameters needed to perform the OAuth request

  • oauth_token
  • oauth_consumer_key
  • oauth_signature
  • oauth_signature_method
  • oauth_timestamp
  • oauth_nonce
  • oauth_version

oauth_consumer_key is obviously the key assigned to your application by Dropbox but the rest aren't really helpful here. oauth_token is the token you obtained in exchange for the entered user credentials, so there is not going to be a problem in obtaning it.

oauth_timestamp is the current UNIX timestamp and it should be the current time. Otherwise, the request will be rejected. It can be easily generated by using this heler static class:

public static class CurrentUNIXTimestamp
{
public static string Get()
{
return Convert.ToString((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
}
}

oauth_nonce in my case will be a simpel GUID. It is generally not advisable to use it due to the possibility of collision issues later on, but it is enough for testing purposes:

Guid.NewGuid().ToString().Replace("-", "")

oauth_version is constantly set to 1.0 - this is defined by the OAuth specifications and shouldn't be changed by any means.

Time to look at the signature. Since it is only used in the OAuth header itself, I decided that I need to generate the OAuth header itself in a separate method, the signature being automatically included there. I added an OAuth folder to the project and created an OAuthClient static class that will help me perform some data manipulations:

So the class itself, with the OAuth header generating method looks like this:

public static class OAuthClient
{
    public static string GetOAuthHeader(Dictionary<string, string> parameters, string httpMethod, string url,
string consumerSecret, string tokenSecret)
    {
        parameters = parameters.OrderBy(x => x.Key).ToDictionary(v => v.Key, v => v.Value);

        string concat = string.Empty;

        string OAuthHeader = "OAuth ";
        foreach (string k in parameters.Keys)
        {
              concat += k + "=" + parameters[k] + "&";
              OAuthHeader += k + "=" + "\"" + parameters[k] + "\", ";
        }

        concat = concat.Remove(concat.Length - 1, 1);
        concat = StringHelper.EncodeToUpper(concat);

        concat = httpMethod + "&" + StringHelper.EncodeToUpper(url) + "&" + concat;

        byte[] content = Encoding.UTF8.GetBytes(concat);

        HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(consumerSecret + "&" + tokenSecret));
        hmac.ComputeHash(content);

        string hash = Convert.ToBase64String(hmac.Hash);
        hash = hash.Replace("-", "");

        OAuthHeader += "oauth_signature=\"" + StringHelper.EncodeToUpper(hash) + "\"";

        return OAuthHeader;
    }
}

For the GetOAuthHeader method I followed the standard pattern:

1. Arrange the parameters alphabetically (that's what OrderBy does in my case).

2. Concatenate parameters (I am building the OAuth header at the same time, as shown by the OAuthHeader string). Keys are separated from values by the equal (=) sign and each pair is separated from another by an and (&) sign.

3. Append the HTTP method used to the beginning of the concatenated parameter list, as well as the base URL where the request is directed. The pattern goes as this: METHOD&URL&CONCATENATED_STRING. Notice that both the method and the URL are separated by an unencoded and (&) sign - the rest MUST be URL-encoded.

4. Encode the base string. HMAC-SHA1 is the only supported signature method and it can be invoked via the HMACSHA1 class.

5. Append the encoded string to the OAuth header.

You probably noticed that I am also calling StringHelper.EncodeToUpper. This is a method I described in my recent Twitter API article. It is related to the way HttpUtility.UrlEncode works, returning lowercase characters instead of uppercase (like it should), therefore messing with the signature.

The method looks like this:

public static string EncodeToUpper(string raw)
{
    raw = HttpUtility.UrlEncode(raw);
    return Regex.Replace(raw, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
}

Now you have the core OAuth mechanism ready. All that needs to be done now is create actually invoke needed methods via HttpWebRequest.

Windows Phone security authentication

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Automation Testing vs. Manual Testing: What's the Difference?
  • Revoking Access to JWTs With a Blacklist/Deny List
  • Component Testing of Frontends: Karate Netty Project
  • What Is High Cardinality?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo