4.1. OAuth 1.0
The OAuth 1.0 protocol1 has different implementations depending on the provider. Twitter for example has 3-legged, PIN-Based, xAuth and Echo. But what we will be looking at is the full flow, also called the 3-legged OAuth. It is so called because it is divided into three steps.
- The consumer obtains a temporary token called the Request Token from the provider through a Request Token URL
- The user is redirected to the provider to authorize the request token. The URL he is redirected to is called the Authorize URL
- The user is redirected back with the authorized request token. The consumer then sends the Request Token to the provider in exchange for an Access Token through an Access Token URL
The URLs involved in this process are called the OAuth endpoints. Here are Tumblr’s OAuth endpoints2:
If the provider offers other implementations or changes to the standard OAuth 1.0 specification, it will be documented. The changes are always very little and you can easily adapt the standard flow to it.
Now, let’s break down the steps.
1. Request Temporary Credentials (Request Token)
The first step is that the consumer requests a temporary credential (request token) from the provider. Here are the parameters to be sent for the request:
I will explain them one after the other.
A URL (yours) the provider will redirect the user to after the authorization step (the second step in the flow) is completed.
The consumer key provided during the OAuth registration.
A random string that MUST be unique across requests.
The signature method for signing the request. Requests are signed with any of the three methods: HMAC-SHA1, RSA-SHA1 and PLAINTEXT. Signing is done to ensure requests are from where they claim to come from. The API documentation will specify the supported method. Most APIs support only HMAC-SHA1.
A timestamp expressed in the number of seconds since January 1, 1970 00:00:00 GMT.
This is optional but if you are including it in your request, it must be “1.0”.
A signature generated based on the signature method. Our focus will be on the HMAC-SHA1 signature method as this is the most common signature method providers support. We will still look at the other methods though.
For the PLAINTEXT signature method, the signature is simply the concatenated encoded value of the consumer secret and token secret.
If there is no token secret yet, as in this case, the signature becomes:
If for example our consumer secret is
RR1ElZScYWhPBT9kb1KhX2uEAY, the signature becomes:
Generating HMAC-SHA1 and RSA-SHA1 signature is a little more complex. Both involves generating a signature base string first. Let’s walk through by assuming a consumer.
Assemble the request parameters
oauth_callback: 'http://tumblr2jekyll.app/callback' oauth_version: '1.0' oauth_nonce: '402057506' oauth_signature_method: 'HMAC-SHA1' oauth_consumer_key: 'f96f91fb6e3d8a54aa' oauth_timestamp: '1444806443'
Percent-encode3 the parameter names and values and sort the parameters alphabetically by the encoded key
oauth_callback: 'http%3A%2F%2Ftumblr2jekyll.app%2Fcallback' oauth_consumer_key: 'f96f91fb6e3d8a54aa' oauth_nonce: '402057506' oauth_signature_method: 'HMAC-SHA1' oauth_timestamp: '1444806443' oauth_version: '1.0'
Create a query string from the encoded parameters. Remember, this is done by going through the name-value pairs, appending the name with ‘=’ character, the value, and ‘&’ character if there are more name-value pairs. This is the parameter string.
Concatenate the HTTP method to be used (in uppercase), the percent-encoded request endpoint and the percent-encoded parameter string with ‘&’ character. This is the signature base string. Our request method is POST, the request endpoint is
https://tumblr.com/oauth/request_token. The request endpoint percent-encoded is
Sign the signature base string using the signature method. For RSA-SHA1, here is how it is done:
key = Client’s RSA private key signature = base64-encode(RSA-SHA1(key, signature_base_string))
For HMAC-SHA1, our focus, here is how it is done:
key = percent-encode(consumer_secret)+'&'+percent-encode(token_secret) signature = base64-encode(HMAC-SHA1(key, signature_base_string))
Notice how the key is same as the signature in the PLAINTEXT method. And since we have no token secret yet, it is same as:
key = percent-encode(consumer_secret)+'&'
Given our consumer secret as RR1ElZScYWhPBT9kb1KhX2uEAY, our key becomes:
key = percent-encode(RR1ElZScYWhPBT9kb1KhX2uEAY)+'&' = RR1ElZScYWhPBT9kb1KhX2uEAY&
and our signature4:
signature = base64-encode(HMAC-SHA1('RR1ElZScYWhPBT9kb1KhX2uEAY&', 'POST&https%3A%2F%2Ftumblr.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Ftumblr2jekyll.app%252Fcallback%26oauth_consumer_key%3Df96f91fb6e3d8a54aa%26oauth_nonce%3D402057506%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1444806443%26oauth_version%3D1.0')) = x/VRlVq4+3FnWBEVQL5OiBGCapY=
Now that we have all our OAuth parameters, including the
oauth_signature, we can send them to the request token URL. There are three ways this can be done - through an Authorization header, POST body parameter or URI query parameter of a GET request. If the API does not support all methods, the document will mention the supported method(s). Tumblr for example supports using an Authorization header only.
The format for the Authorization header is:
Here is how the parameter list is created:
- The parameter names and values are percent-encoded
- The parameter name is followed by a ‘=’ character, and the value enclosed in quotes
- This is repeated for other parameters.
- The parameters are separated with a ‘,’ character
This is what the Authorization header for our request will look like. I have added line breaks for clarity.
If we were to use GET, this is what the request would look like:
And the POST version:
Remember though, the parameter names and values must be percent-encoded. Also note that Tumblr supports only the Authorization header method of making an OAuth request. I only added the GET and POST requests to show how the requests can be made using these methods.
Step 1 above will return
oauth_callback_confirmed in this response form:
The consumer then parses the returned body and redirects the user to the authorization endpoint with the
oauth_token as a URL query parameter. We have a token secret now (
oauth_token_secret) and will be needing it in the next step. But for now, we redirect the user to the authorization URL.
The authorize endpoint tells the user the consumer wants his authorization. If he accepts, the provider redirects the user back to the specified oauth_callback with the parameters
oauth_verifier passed through the URL query string.
3. Request Token Credentials (Access Token)
Now that the user has been redirected back to the consumer’s
oauth_callback, the consumer exchanges the
oauth_token for an access token. The process is very similar to the first step where we requested the request token. Continuing with our example consumer, the difference is that we will now add the parameters -
oauth_verifier (returned by the provider in step 2) and will remove the
oauth_callback parameter. Our focus is on the HMAC-SHA1 method so we will only calculate the signature based on that.
Our OAuth parameters now become:
Using these parameters, we go over our signing process again.
Here are our new parameters, sorted alphabetically and percent-encoded:
Our parameter string then becomes:
Now that we have our parameter string, our request method as POST and our authorization URL as https://tumblr.com/oauth/access_token, we can calculate the signature just as before. Our signature base string becomes:
We have a token secret now. Remember the one from the last step? Yes, that. This changes our key.
Take it from here. Revisit the HMAC signature algorithm and try to calculate the signature yourself. This should be the result:
Again we generate our Authorization header as before:
This will return the authorized access token and secret in the format
Making authenticated requests
Now that the consumer has the access token, all requests to API endpoints that require authorization must be signed with it. Signing the requests follows the same process as we’ve seen in the last two steps.
Let’s see an example with the Tumblr API. Let’s retrieve the authenticated user’s dashboard. You can find the documentation for that here: https://www.tumblr.com/docs/en/api/v2#m-ug-dashboard. The request endpoint is
https://api.tumblr.com/v2/user/dashboard and the required HTTP method is
GET. There are some request parameters we can include. One of such is type. We will be using it to filter the request to show only posts of the type quote.
Here are our application keys and token details:
- Consumer key:
- Consumer secret:
- OAuth access token:
- OAuth token secret:
The first step is to list our parameters. This will include the necessary request parameters and the OAuth parameters.
Next we sort, percent-encode and build our parameter string.
We also calculate our key by concatenating the percent-encoded consumer secret and percent-encoded token secret with &.
And from this, we calculate our HMAC-SHA1 signature.
Just one more thing - build the Authorization header for the request.
Here is the full request:
Oauth.net and Flickr have these pictorial break down of the flow. It will help you understand and remember better.
Here, spaces are encoded as %20 and not as + as with URL encoding for the
application/x-www-form-urlencodedcontent type ↩