Understanding Request Signing For Oauth 1.0a Providers

I am very familiar with Oauth 2.0, but recently I had to work with Twitter and it was not as smooth of an experience as other providers such as Google and Facebook.  This is because Twitter uses Oauth 1.0a and requires request signing.

Oauth 1.0a requires requests to be signed using HMAC and a secret key.  Using this protects communication between the client and the server, but how do we accomplish this task?

Creating a signature happens through the following steps:

  1. Collect required parameters
  2. Collect query string and body parameters
  3. Create a signature base string
  4. Hash with HMAC and a secret key
  5. Use the signature in your request

For the sake if this article, there will be some heavy references to JavaScript, but you can apply this knowledge to any programming language.

1. Collect required parameters

Twitter, like all Oauth 1.0a providers have a set of required parameters.  They will probably be similar if not the same across all providers.  Let’s look at the following required elements:

All of the above properties will have static values provided by the Oauth provider except the oauth_nonce and oauth_timestamp.  These are dynamic values that must be set during run time.  The nonce is a random string value, something I normally set as a hash of the timestamp.  The timestamp is the time from epoch.

If using JavaScript, you can get the epoch by running the following:

With the required parameters in hand, you can now start collecting the query and body parameters.

2. Collect query string and body parameters

All parameters, query and body, must be collected before creating a signature base string.  In addition, each of these parameters must be percent encoded.  Let’s assume we are doing a POST request and there is only one body parameter called oauth_callback.  Our new parameter list now looks like the following:

With all parameters collected we can move on to creating a signature base string.

3. Create a signature base string

The signature base string has some very strict requirements, but it is the final string that will be hashed using the appropriate hashing algorithm.  The base string must be formatted like the following:

Let’s assume for this example we are going to use the https://api.twitter.com/oauth/request_token endpoint.  The generic format I posted above, is far to general for what we need to accomplish.  To be more specific, the request uri and all parameters need to be percent encoded.  In addition to being percent encoded, the parameters need to be in alphabetical order.  To accomplish this, you might do something like the following in JavaScript:

This is the string that will be used to create a hashed signature.

4. Hash with HMAC and a secret key

We will now create a hashed signature string from our signature base string.  If you’re using Twitter, the requirement is HMAC-SHA1 which isn’t necessarily the strongest form of SHA, but it works.

Note that you cannot use your raw consumer secret key to sign the request.  You must concatenate the secret key and Oauth token secret provided by your Oauth provider for signing.  These must be concatenated with an ampersand.

Above is JavaScript code for creating a secret signing key to be used in the HMAC function.  If the oauth token secret does not exist, continue to add the ampersand, but omit the oauth token secret.

Let’s look at the following PHP function:

If you’re using PHP, don’t forget to convert the HEX $signature string to a BASE64 encoded $signature string.  If you wanted to do this with JavaScript, I highly recommend using the open source jsSHA library as it has some really great hashing algorithms including HMAC-SHA1.  With jsSHA your signature would be generated like follows:

The signature might have some slashes and equals sign characters in it.  This signature needs to be percent encoded.  In JavaScript you can do the following:

With the percent encoded signature string you are now ready to create an authorization header for use with an API.

5. Use the signature in your request

Now that you have a signature you can format an authorization header.  Based on the required, query, and body parameters, our authorization header should look like this:

Note that I made up all the values above, but the keys are accurate.  Only the required parameters show up in the header.  The query and body parameters do not show up in the header, only in the query and body.

In AngularJS, the post request might look something like this:

When working with a provider that uses Oauth 1.0a, every request must be signed.  I personally find it to be a hassle, but it is sometimes out of our control.

Below is a CodePen.io example that I wrote demonstrating the signing process.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • Joel

    Hi, this is very well done tutorial, could you rework this into a plain javascript version however?

    • If you have an oauth_token_secret to work with, you would append it after the ampersand (&) in this line:

      As for a JavaScript version, I’m assuming the actual request and header assignment that I did in AngularJS is throwing you off?

      Regards,

      • Joel

        You are also using the oauth_token_secret inside of the secret_signing_key. Which I shouldn’t have because the point of this is to get the request token?

        The header in the angular is what is throwing me off correct

        • In this particular example that I made, yes we are aiming to get the request token so there shouldn’t be an oauth_token_secret yet. The request token call should return an oauth_token_secret which you will use in future requests appended after the ampersand.

          In the above line we are creating our secret signing key which will get passed into the HMAC function. If the oauth_token_secret doesn’t exist (it won’t always exist), you will leave the ampersand, but just remove the oauth_token_secret. In the HMAC function in my example, I just chose to deconstruct the secret_signing_key.

          Does that make better sense?

          You may want to visit this post regarding HTTP requests with vanilla JavaScript:

          http://stackoverflow.com/a/9713078/498479

          Don’t hesitate to ask further questions if something is not clear.

          Regards,

  • WWII

    Where does Twitter get the oauth_callback parameter? wouldn’t it need it in order to generate the same HMAC code? do we pass it in the body of the POST request?