Fork me on GitHub
Join For Free

The OAuth Bible

By @Nijikokun

I tried to make this as understandable as possible for any party reading it which means that the wording, references, and terminology used may not reflect that of a technical paper or resource. Excuse me if you may for I wish all to understand this, and not just those with a degree in understanding technical jargon.

Terminology / Reference

TOC Signed Requests

Note

This section is in regards to OAuth 1.0

Signing requests is more than just the signature so in this section we will look at how the signature process should be handled and how each parameter should be used with references to flows.

In this step the Application takes all the information it has gathered and generated and places it in a single location.There are two ways of transporting this information, through the OAuth header or Query string. I highly recommend going the header route for better security.

Before we can generate this string we must gather all the required parameters and their values, some of these are used inside of the string directly and others in-directly through the encryption or encoding of the signature.

Signature Base String

Gathering the Method of the request, the URL of the request (or in the case of OAuth Echo the verify credentials uri) and the Parameters joined together by the & symbol would look like this raw (example from twitter):

POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521

Signing Key

The signature base string is then encrypted with a salt called the signing key which is always a joining of the OAuth Consumer Secret and Token Secret once again by the & character like so:

kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE

Note

Sometimes in case of RSA Encryption and xAuth the signing key may only be the Consumer Secret with the & symbol appended or not.

For more insights check out the following lines, #233 & #283 from the mashape-oauth node module.

Encoding the Signature

At last, we are able to encode our signature using these two strings of information. If you check out the terminology section you would find that there are three ways we can do this. PLAINTEXT, HMAC, and RSA Encryption. Each method is slightly different, and carry their own set of pros and cons.

PLAINTEXT

Here we ignore any encoding and simply pass along the Signature Key as human readable text.

HMAC-SHA1

This encoding method outputs our key into binary which we update our base with, which after this step gets Base64 encoded into it's final signature string:

tnnArxj06cWHq44gCs1OSKk/jLY=

RSA-SHA1

On the more complex side of encoding and security we have the RSA method that we have to encode the generated Private Key against our Signature Base.

Note

For clarification on how to pass your private key check out line #74 from the mashape-oauth node module.

Then on the service side they verify the public key that was generated along-side the private key against the encoded string passed as oauth_signature.

OAuth Header

The OAuth header is a part of the signed request, it contains the oauth_signature and oauth_signature_method parameters and their values. It is a single string and separated generally by a comma (spaces are supported here by some services, stick to comma by default unless told otherwise by the service) and named Authorization with OAuth being the Bearer, in other flows this may change such as the Mac Bearer and other similar methods.

The header itself is built up by all the oauth_* parameters sorted (by name, then some more complex things). Here is an example taken from Twitter for getting a Request Token:

POST /oauth/request_token HTTP/1.1
User-Agent: themattharris' HTTP Client
Host: api.twitter.com
Accept: */*
Authorization:
        OAuth oauth_callback="http%3A%2F%2Flocalhost%2Fsign-in-with-twitter%2F",
              oauth_consumer_key="cChZNFj6T5R0TigYB9yd1w",
              oauth_nonce="ea9ec8429b68d6b77cd5600adbbb0456",
              oauth_signature="F1Li3tvehgcraF8DMJ7OyxO4w9Y%3D",
              oauth_signature_method="HMAC-SHA1",
              oauth_timestamp="1318467427",
              oauth_version="1.0"

The oauth_callback is what twitter will invoke or respond to when the authentication step happens, some services tell you they have successfully confirmed this information with a oauth_callback_confirmed token (This should be the de-facto situation).

Now, lets see the example response:

HTTP/1.1 200 OK
Date: Thu, 13 Oct 2011 00:57:06 GMT
Status: 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 146
Pragma: no-cache
Expires: Tue, 31 Mar 1981 05:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
Vary: Accept-Encoding
Server: tfe

oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&
oauth_token_secret=veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI&
oauth_callback_confirmed=true

Great, 200 response with the oauth_token, oauth_token_secret and oauth_callback_confirmed parameters. This is perfect, now you can use the oauth_token_secret for creating your signature for the access token and oauth_token for authenticating the request.

Generally, the oauth_token will be sent along as a query parameter ?oauth_token=[token goes here] on the authenticate endpoint when doing a 3-Legged OAuth 1.0a request which should give you back the oauth_token and oauth_verifier which then are used as well in your Access Token request [19].

TOC OAuth 1.0a (One Leg)

What is commonly known as two-legged is actually one legged, there is only one step, thus you are standing on one leg.

Notice

Google requires a custom parameter that must be added to the query string of the url you are request called xoauth_requester_id [R] and many others.

However, they have depricated OAuth 1.0a in favor of OAuth2. So make sure you are up to date on service authentication protocols and quirky requirements as the following information may not always be all that is required.

  1. Application sends a signed request to the Service giving it:
    • oauth_token Empty String
    • oauth_consumer_key
    • oauth_timestamp
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version Optional
  2. Service Validates and Grants Access to Resources.
  3. Application Utilizes Requested Resources

This is probably the most quickest method of consuming an OAuth implementation however it comes with a few drawbacks on security which you can assume for yourself whether it is the best for your application.

TOC OAuth 1.0a (Two Legs)

The real two-legged OAuth implementation, so lucrative it's like finding a diamond in the rough. Here we also avoid the user authentication step but follow the other flows of OAuth.

  1. Application sends a signed request for a Request Token:
    • oauth_consumer_key
    • oauth_timestamp
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version Optional
  2. Grants application Request Token:
    • oauth_token
    • oauth_token_secret
    • … Additional Parameters / Arguments
  3. Exchange Request Token for Access Token, signed request
    • oauth_token Request Token
    • oauth_consumer_key
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version
  4. Service grants Access Token & Token Secret (same arguments generally as Step 2)
  5. Application uses oauth_token & oauth_token_secret to access protected resources.

Here is the actual flow of OAuth 1.0a 2-legged, here we can see the extra security measures in place to make sure a secure access connection has been made without bothering the user to authorize details.

TOC OAuth 1.0a (Three Legged)

This flow is the full experience, the grand finale, the whole shebang. It's the full-flow of OAuth 1.0a, and the most complex, excluding the other two variants on it. The user interaction in the middle of the flow is usually what causes most confusion.

  1. Application sends a signed request for a Request Token:
    • oauth_consumer_key
    • oauth_timestamp
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version Optional
    • oauth_callback
  2. Grants application Request Token:
    • oauth_token
    • oauth_token_secret
    • oauth_callback_confirmed
    • … Additional Parameters / Arguments
  3. Send user to authorize url using:
    • oauth_token
  4. Prompts user to authorize / grant access
  5. User grants access
  6. Directs back to application with:
    • oauth_token
    • oauth_verifier
  7. Exchange Request Token / Verifier for Access Token, signed request
    • oauth_token Request Token;
    • oauth_consumer_key
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version
    • oauth_verifier
  8. Service grants Access Token & Token Secret (same arguments generally as Step 2)
  9. Application uses oauth_token & oauth_token_secret to access protected resources.

Notice

On Step 6 if the oauth_verifier has not been set, this is a failed OAuth 1.0a 3-Legged implementation and probably only requires the oauth_token to be sent. Rarely seen but they exist.

The most secure OAuth implementation so far, yet a little more complicated seeing as the user is a part of the handshake and must interact with interfaces during the transactions.

TOC OAuth 1.0a (Echo)

Not necessarily the most common of OAuth implementations, but it exists. Created by Raffi from Twitter it uses two extra headers in the initial request token step to validate your user on their behalf by delegation.

So essentially the Service will authenticate and verify the user against the originating service such as Twitter.

  1. Application sends a signed request along with any data and:
    • oauth_consumer_key
    • oauth_timestamp
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version Optional
    • oauth_callback
    • Along with two additional headers:

    • X-Auth-Service-Provider
    • X-Verify-Credentials-Authorization
  2. Service takes the additional headers and validates against the Origin Service.
  3. Service then validates against given information and returns protected resource information. This could be storing an image, generating the url and returning that information.

TOC OAuth 1.0a (xAuth)

xAuth is a way for desktop and mobile apps to get an OAuth access token from a user’s email and password, and it is still OAuth. So the third-party will ask for your credentials on the origin service to authenticate with.

The xAuth process will give back read-only, or read-write access tokens. Some limitations can apply, as in the Twitter spec Direct Messages read access is not provided and you must use the full flow.

Notice

The user's credentials should never be kept by the application requesting them.

  1. Application Requests User Credentials
  2. Application creates signed request for Access Token:
    • oauth_consumer_key
    • oauth_timestamp
    • oauth_nonce
    • oauth_signature
    • oauth_signature_method
    • oauth_version Optional
    • oauth_callback
    • Along with additional parameters:

    • x_auth_mode = client_auth
    • x_auth_username
    • x_auth_password
    • x_auth_permission Optional; Scope of the requested token [17]
  3. Service validates user details and grants Access Token
    • oauth_token
    • oauth_token_secret
  4. Application uses Access Token to retrieve protected resources.

TOC OAuth 2 (Two Legged)

By far the easiest to explain, here we have what is called a Client Credentials authorization flow. [26, 4.4] Which is also basically just the Resource Owner Password flow without the username and password appended to the encoded query passed along as the body, unless the service states through the url in which case is wrong.

Info

If you are using basic, you will need to additionally pass along an Authorization header with the bearer type as Basic and as the value you use client_id : client_secret Base64 encoded.

Authorization: Basic Base64(client_id:client_secret)

Client Credentials

  1. Application makes request to Service:
    • grant_type = client_credentials

    If you aren't using the Authorization header:

    • client_id
    • client_secret
  2. Service responds with Access Token:
    • access_token
    • expires_in
    • token_type

Implicit Grant

You will notice that we don't send the secret, this is actually the correct way of sending information; However, like all the other parts of OAuth there are services that don't follow this paradigm so in some cases it may be required. Also, the header should not be used in this case, and once again some services may completely ignore the specifications. Make sure to check the documentation of the service before assuming.

  1. Application makes request to Service:
    • response_type = token
    • redirect_uri This is a server-side Redirection URI hosted by the provider or yourself.
    • scope
    • state Optional
    • client_id
  2. User may need to authorize, this is not required, but we will assume they are granting access.
    • username
    • password
  3. Service will respond with the access_token inside of the redirect_uri, surprisingly enough inside of a #hash fragment (as some server side components cannot read this information). You may want to take time to extract other information that is sent along here such as:
    • state Optional; If used in the prior step.
  4. Application will then follow the Redirection URI without the hash fragment (detailed in the spec, I assume you must remove this with client-side scripting as it will send the hash if you don't).
  5. Redirection URI will respond with a Script / HTML Fragment or Page containing the access_token, and any other parameters you may need. (Spec is not specific on parameter or script details, Freedom!).

Resource Owner Password

Basically OAuth 1.0a Echo… without the signing and complications. Let's do this.

  1. Application request credentials, shown below, from resource owner (also known as the user).
    • username
    • password
  2. Application makes request to Service using the given credentials as a query string for the body:
    • grant_type = password
    • username
    • password
    • It should look like this:

      grant_type=password&username=my_username&password=my_password

      If you aren't using the Authorization header, these must be passed as well:

    • client_id
    • client_secret
    • Which would become:

      grant_type=password&username=my_username&password=my_password&client_id=random_string&client_secret=random_secret
  3. Service responds with Access Token details and expiration information:
    • access_token
    • expires_in
    • token_type

TOC OAuth 2 (Three Legged)

OAuth2 three-legged cuts out a lot of clutter just like the two-legged, no longer are things so complex with signing your requests.

Fun Fact

Scope by spec was to be space seperated (i.e. user pull-request) to which nobody followed and we are now left in a state of constant wonder as to what the next api we tackle uses.

  1. Application redirects User to Service for Authorization:
    • client_id
    • redirect_uri
    • response_type [20, 4.1.1]
    • state Optional; Unique identifier to protect against CSRF [25]
    • scope Optional; what data your application can access.
    • Example Authorization URL (Not-Encoded for Readability):

      https://oauth_service/login/oauth/authorize?client_id=3MVG9lKcPoNINVB&redirect_uri=http://localhost/oauth/code_callback&scope=user
  2. User logs into the Service and grants Application access.
  3. Service redirects User back to the redirect_url with:
    • code
    • state
  4. Application takes the code and exchanges it for an Access Token:
    • client_id
    • client_secret
    • code
    • redirect_uri Optional; see [20, 4.1.3]
    • grant_type = "authorization_code" [20, 4.1.3]
  5. If client_id and client_secret are valid the Service will invoke a callback on redirect_url that contains an access_token:
    • access_token
    • expires_in
    • refresh_token
  6. Application stores access_token to use in subsequent requests in various manners dependent on the Service.
    • Generally this value is stored in a session or cookie, and then placed into the request as an Authorization: [Bearer] access_token header string where [Bearer] is the Header Authorization Bearer Name it could be Bearer, OAuth, MAC, etc…

TOC OAuth 2 (Refresh Token)

In OAuth2 the access_token sometimes, which is most of the time, has a limited lifetime expectancy. We can assume by the expires_in parameter passed along at the Access Token response stage whether it will live forever or decay in a certain amount of time.

If an expired token is used the Service will respond with a Session expired or Invalid response error. This means we must use the refresh_token along with a few other previously obtained parameters to generate a new one. A lot easier than the whole flow.

  1. Create request to Service Refresh Token URI:
    • grant_type = "refresh_token"
    • scope Optional; Cannot have any new scopes not previously defined.
    • refresh_token
    • client_id
    • client_secret
  2. Service validates and responds with the following parameters:
    • access_token
    • issued_at

TOC Sources

Here is a long, windy list of places where I tracked down specific information regarding certain legs or auth specification excluding the original RFC and it's revisions.

  1. Authorizing with OAuth - Flickr Documentation
  2. OAuth on Bitbucket - Bitbucket Documentation
  3. OAuth Documentation - Twitter Documentation
  4. OAuth Extended Flows
  5. 2-Legged OAuth - OAuth-PHP
  6. OAuth for Consumer Requests
  7. OAuth Example - term.ie
  8. OAuth 1.0 Guide - Heuniverse
  9. OAuth 1.0a Diagram
  10. OAuth Wiki
  11. 2-Legged OAuth 1.0 & 2.0 - DZone
  12. OAuth & OAuth2 - Google Documentation
  13. What is 2-legged OAuth? - Nerdbank
  14. List of Service Providers - Wikipedia
  15. OAuth Echo - mobypicture
  16. OAuth Echo - Twitter
  17. Advanced API - Vimeo Developer();
  18. About xAuth - Twitter xAuth Documentation
  19. Implementing Sign-in - Twitter Sign-in Documentation
  20. RFC6749 - IETF
  21. Web Application Flow - Github OAuth2
  22. OAuth2 Quickstart - Salesforce
  23. Authentication Mechanisms - Geoloqi
  24. Understanding Web Server OAuth Flow - Salesforce
  25. CSRF & OAuth2 - Springsource
  26. OAuth v2-31 - IETF
  27. Resource Owner Flow - Hybris