Understanding OAuth – Tweeting from Scratch, Part 1

Share this article

A common complaint about OAuth is that it is very difficult to understand, but perhaps some of that confusion is because of an expectation that the abstraction provided by a third-party library will erase the need to understand the steps of an OAuth transaction – it does not. This two-part article demonstrates how how OAuth v1 works by explaining the process of connecting a PHP application to the Twitter API using only a few built-in functions to post a message to a user’s Twitter stream. The example code provided in this article is intended for educational purposes only. It lacks much practical use and error handling, Any real development should take advantage of an existing OAuth library, but after reading this article you’ll have a better understanding of how OAuth works and will be better equipped to troubleshoot any problems that may arise.

Obtaining Consumer Credentials

Posting to Twitter on behalf of a user without asking for a username and password combination every time requires a sort of “valet key”… this key is OAuth. In OAuth terms, your client application is called the consumer, the user is called the resource owner, and Twitter is the server or service provider. Before Twitter will accept a post from your application, you need to obtain your own client credentials: the Consumer Key and Consumer Secret. Twitter, like most services that provide a public API, will grant you a key and secret after completing a registration form (available at dev.twitter.com/apps). With Twitter, you need to supply some information that will identify your application to the user during the authorization process, specifically its name, description, and website URL. You also need to enter a Callback URL, which I’ll explain later. Once you have submitted the Create an Application form, you will be taken to a Details page for your new application. Scroll down to find your Consumer Key and Secret. You’ll need these along with the handful of endpoint URLs that are listed. Notice the application is granted Read Only access by default; since it will be posting tweets, you need to click the Settings tab and change the access to “Read and Write”.

Authorizing the Application

The Consumer Key and Consumer Secret allow your application to talk to the Twitter API, but those alone won’t let it post tweets on another user’s behalf. You need access credentials: an Access Token and Access Secret. To obtain these through a request to the Service Provider (Twitter) in a short conversation using the consumer credentials involving Twitter and the end-user. Obtaining the access credentials can be fairly painful, but luckily you only need to do this once per user. You can save the credentials indefinitely for later use and not require the user to reauthorize your application. The conversation requesting the access credentials requires its own set of credentials: the Request Token and Request Secret.

Authorization Step 1: Request Credentials

The authorization process typically starts by directing the user to an Authorize Twitter page. This is a page you create that initiates the request for a Request Token from Twitter and begins the OAuth authorization process. It must generate a URL used to grab the Request Credentials, and once you have the credentials you can redirect the user to Twitter to grant the application permission to post. Requesting the Request Credentials requires a signed request, which means you need to send an OAuth signature along with other important parameters in the request. The signature is a base64-encoded hashed list of the request parameters. In Twitter’s case, the hashing algorithm is HMAC-SHA1. The signing process prevents anyone else from posing as your application with your credentials even though the Consumer Key is transmitted in plain text. The signature can only be reproduced by you (the Consumer) and the server (Twitter) because you two are the only entities that should know the Consumer Secret that hashes the signature. Lets build a string the signature is based on:
<?php
$requestTokenUrl = "http://api.twitter.com/oauth/request_token"; 
$authorizeUrl = "http://api.twitter.com/oauth/authorize";
$oauthTimestamp = time();
$nonce = md5(mt_rand()); 
$oauthSignatureMethod = "HMAC-SHA1"; 
$oauthVersion = "1.0";

$sigBase = "GET&" . rawurlencode($requestTokenUrl) . "&"
    . rawurlencode("oauth_consumer_key=" . rawurlencode($consumerKey)
    . "&oauth_nonce=" . rawurlencode($nonce)
    . "&oauth_signature_method=" . rawurlencode($oauthSignatureMethod)
    . "&oauth_timestamp=" . $oauthTimestamp
    . "&oauth_version=" . $oauthVersion);
Some of the above variables may be fairly obvious – $requestTokenUrl was obtained from Twitter when you were granted consumer credentials, and $oauthTimestamp is the current UNIX epoch time. The less obvious item is $nonce, which is nothing more than a random string used only once (a difference nonce is used for each transaction). Typically an MD5-hashed random number works fine as a nonce. There is also $oauthSignatureMethod
which is always HMAC-SHA1 for Twitter, and the $oauthVersion which is currently v1.0 for Twitter. Next, the string for the signature is constructed as $sigBase. OAuth says that the signature base must be the HTTP method (GET in this case) followed by an “&”, followed by the URL-encoded request URL ($requestTokenUrl) followed by another “&”, and finally a URL-encoded and alphabetized list of parameter key/value pairs (the values of which must also be encoded) separated by “&”s. Note that when OAuth wants something URL-encoded, it means RFC-3986. PHP’s rawurlencode() function works because it encodes spaces as “%20” instead of “+” as urlencode() does. You also need a Signing Key. The key is always the Consumer Secret followed by an “&” and either 1) the OAuth Token Secret (which is part of the Token Credentials you don’t have yet), or 2) nothing. Then you can generate the final signature using PHP’s built-in hash_hmac() function.
<?php
$sigKey = $consumerSecret . "&"; 
$oauthSig = base64_encode(hash_hmac("sha1", $sigBase, $sigKey, true));
You put all the pieces together to construct a URL to request the Request Credentials:
<?php
$requestUrl = $requestTokenUrl . "?"
    . "oauth_consumer_key=" . rawurlencode($consumerKey)
    . "&oauth_nonce=" . rawurlencode($nonce)
    . "&oauth_signature_method=" . rawurlencode($oauthSignatureMethod)
    . "&oauth_timestamp=" . rawurlencode($oauthTimestamp)
    . "&oauth_version=" . rawurlencode($oauthVersion)
    . "&oauth_signature=" . rawurlencode($oauthSig); 

$response = file_get_contents($requestUrl);
You’ll want a lot more error handling for anything beyond this simple demonstration, but for now I assume nothing will ever go wrong and you are able to receive the temporary Request Credentials in $response. The response sent back from Twitter looks like this:
oauth_token=mjeaYNdNYrvLBag6xJNWkxCbgL5DV6yPZl6j4palETU&oauth_token_secret=W45dnBz917gsdMqDu4bWNmShQq5A8pRwoLnJVm6kvzs&oauth_callback_confirmed=true
The oauth_token and oauth_token_secret values are extracted from the response and are used to construct the next link the user goes to for the second step in the authorization process. It’s a good idea to store the Request Credentials in the user’s session so they are available when the user returns from Twitter’s authorization page. The Authorization URL is provided on the Details page after registering your application with Twitter.
<?php
parse_str($response, $values);
$_SESSION["requestToken"] = $values["oauth_token"];
$_SESSION["requestTokenSecret"] = $values["oauth_token_secret"];

$redirectUrl = $authorizeUrl . "?oauth_token=" . $_SESSION["requestToken"]; 
header("Location: " . $redirectUrl);
Now that the application can send users to Twitter for authorization, it is a good time to add a Callback URL so Twitter can send them back to the application! The Callback URL is simply an address that Twitter will direct the user to after he has authorized your application to send tweets on his behalf, and is specified on the Detail page’s Settings tab. When Twitter redirects the user to the Callback URL, it appends two additional parameters: your oauth_token from the initial request which can be used for verification, and oauth_verifier which is used in obtaining the Authorization Credentials. Of the three sets of credentials needed to post tweets, you now have two – the Consumer Credentials and the Request Credentials. Next up: Access Credentials!

Authorization Step 2: Access Credentials

To obtain the Access Credentials you need the oauth_token
, oauth_token_secret, and the newly obtained oauth_verifier. This step requires another signed request, this time to the Access Token URL displayed on the Details page.
<?php
$oauthVersion = "1.0";
$oauthSignatureMethod = "HMAC-SHA1"; 
$accessTokenUrl = "http://api.twitter.com/oauth/access_token"; 
$nonce = md5(mt_rand()); 
$oauthTimestamp = time();
$oauthVerifier = $_GET["oauth_verifier"];
The $accessTokenUrl is the next endpoint obtained from the Details page. A new $oauthTimestamp and $nonce are generated, and $oauthVerifier is sent back from the Twitter Authorization page. Not listed, but in the $_SESSION array, are the request credentials from the previous step that are also required. This step of the authorization process requires another signed request. Once the signature is built, it is used with the request for Access Credentials.
<?php
$sigBase = "GET&" . rawurlencode($accessTokenUrl) . "&"
    . rawurlencode("oauth_consumer_key=" . rawurlencode($consumerKey)
    . "&oauth_nonce=" . rawurlencode($nonce)
    . "&oauth_signature_method=" . rawurlencode($oauthSignatureMethod)
    . "&oauth_timestamp=" . rawurlencode($oauthTimestamp)
    . "&oauth_token=" . rawurlencode($_SESSION["requestToken"])
    . "&oauth_verifier=" . rawurlencode($oauthVerifier)
    . "&oauth_version=" . rawurlencode($oauthVersion)); 
$sigKey = $consumerSecret . "&"; 
$oauthSig = base64_encode(hash_hmac("sha1", $sigBase, $sigKey, true));

$requestUrl = $accessTokenUrl . "?"
    . "oauth_consumer_key=" . rawurlencode($consumerKey)
    . "&oauth_nonce=" . rawurlencode($nonce)
    . "&oauth_signature_method=" . rawurlencode($oauthSignatureMethod)
    . "&oauth_timestamp=" . rawurlencode($oauthTimestamp)
    . "&oauth_token=" . rawurlencode($_SESSION["requestToken"])
    . "&oauth_verifier=" . rawurlencode($oauthVerifier)
    . "&oauth_version=". rawurlencode($oauthVersion)
    . "&oauth_signature=" . rawurlencode($oauthSig); 

$response = file_get_contents($requestUrl);
This time $response has the very useful screen_name, user_id and the much awaited Access Credentials!

Summary

This concludes the authorization part of this article. So far you’ve learned how to create a new Twitter application and use the provided consumer credentials to step through the OAuth “dance” to obtain the access credentials. In the second and final part of this series I’ll discuss using the access credentials to post a tweet to the user’s Twitter stream. Image via Quin / Shutterstock

Frequently Asked Questions (FAQs) about OAuth 1.0

What is the difference between OAuth 1.0 and OAuth 2.0?

OAuth 1.0 and OAuth 2.0 are both protocols for authorization, but they have some key differences. OAuth 1.0 uses a more complex process involving cryptographic signatures for security, while OAuth 2.0 uses bearer tokens and SSL/TLS for security. OAuth 2.0 is generally considered easier to work with due to its less complex nature, but some developers prefer OAuth 1.0 for its robust security features.

How does OAuth 1.0 handle security?

OAuth 1.0 uses cryptographic signatures to ensure the security of data. These signatures are created using the client’s secret key and the request’s parameters. This method ensures that the data cannot be tampered with during transmission and that the client is who they claim to be.

What is a nonce in OAuth 1.0?

A nonce is a random string that is used only once in each request. It is used in combination with the timestamp to prevent replay attacks. The server keeps track of all used nonces within the timestamp window to ensure that each one is unique.

How does OAuth 1.0 handle user authentication?

OAuth 1.0 does not handle user authentication itself. Instead, it delegates this task to the service provider. The service provider will authenticate the user and then provide the client with an access token that can be used to access the user’s resources.

What is the purpose of the request token in OAuth 1.0?

The request token is used in the initial step of the OAuth 1.0 flow. The client obtains a request token from the service provider, which is then used to redirect the user to the service provider for authentication. Once the user has been authenticated, the request token is exchanged for an access token.

How does OAuth 1.0 handle signatures?

In OAuth 1.0, signatures are used to ensure the integrity and authenticity of the data. The signature is created by taking the HTTP method, the base URL, and the sorted and encoded parameters, and then creating a HMAC-SHA1 hash using the client’s secret key.

What is the role of the verifier in OAuth 1.0?

The verifier is a value that is returned by the service provider after the user has been authenticated. It is used by the client to exchange the request token for an access token. The verifier ensures that the user has indeed authorized the client to access their resources.

Can OAuth 1.0 be used with mobile applications?

Yes, OAuth 1.0 can be used with mobile applications. However, it can be more complex to implement than OAuth 2.0 due to the need for cryptographic signatures. Some mobile platforms also have limitations that can make the implementation of OAuth 1.0 more challenging.

What is the lifespan of an access token in OAuth 1.0?

The lifespan of an access token in OAuth 1.0 is determined by the service provider. Some providers may issue tokens that last indefinitely, while others may issue tokens that expire after a certain period of time. Once an access token has expired, the client must obtain a new one.

How does OAuth 1.0 handle revoking access?

In OAuth 1.0, revoking access is handled by the service provider. If a user wishes to revoke a client’s access to their resources, they can do so through the service provider’s interface. Once access has been revoked, the client’s access token will no longer be valid.

Dustin RunnellsDustin Runnells
View Author

Dustin Runnells is a passionate technology enthusiast in Rochester, NY, with a special interest in Linux and social media. While juggling a full-time job as a professional programmer at a real company and being a loving husband and father of three, Dustin fills whatever time he has left tinkering on his personal projects. Dustin is MySQL Core Certified, LPI1 Certified, and a Zend Certified Engineer.

Advanced
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week