Understanding OAuth – Tweeting from Scratch, Part 2

Share this article

Welcome back to Understanding OAuth – Tweeting from Scratch. This is Part 2 of the two-part series and picks up right where we left off in Part 1 with your returned Access Credentials. Since obtaining the credentials is the grueling part of the process, there’s not much more left to do except posting a tweet on the user’s behalf. Hopefully you’ll find the final steps to be a lot easier to follow and more fun to implement.

First things first, you should at least store the user specific details and credentials from Part 1 in $_SESSION so they can be used later, though most likely you’ll want to store the information in a database so you can retrieve them whenever you like to send tweets on behalf of others.

<?php
//...
$response = file_get_contents($requestUrl);
parse_str($response, $values);

$_SESSION["accessToken"] = $values["oauth_token"];
$_SESSION["accessTokenSecret"] = $values["oauth_token_secret"];
$_SESSION["twitterUserId"] = $values["user_id"];
$_SESSION["twitterUsername"] = $values["screen_name"];

// Redirect the user to the application's form 
header("Location: /postTweet.php");

Since your application has the necessary Access Credentials and you’ve tucked them away safely for future use, you can redirect the user to a form where he can enter the text of his tweet.

<form action="/postTweet.php" method="post">
 <textarea name="tweet" rows="3" cols="50"></textarea>
 <br>
 <input type="submit" value="Send">
</form>

Posting to Twitter

There is plenty you can do with the Twitter API once you have Access Credentials (full API documentation can be found at dev.twitter.com/docs/api). For this article I’m showing just the use of statuses/update to to post a tweet. You can request many of the API calls to respond with XML or JSON formatted data simply by adding .xml or .json to the end of the URL. Personally I find JSON far easier to deal with than XML.

statuses/update requires an HTTP POST to be made sending your OAuth parameters in the HTTP header. Previously you only used GET in the conversations with Twitter.

All OAuth v1 Twitter API resource URLs begin with “http://api.twitter.com/1/” and end with the resource name followed by .xml or .json. The only credentials you need from now on are your Consumer Credentials and the Access Credentials; the Request Credentials are discarded since they were only necessary for the authorization process.

Building the signature is performed the same as before except you now include the Access Token Secret in $sigKey.

<?php
$oauthVersion = "1.0";
$apiResourceUrl = "http://api.twitter.com/1/statuses/update.json"; 
$nonce = md5(mt_rand()); 
$oauthSignatureMethod = "HMAC-SHA1"; 
$oauthTimestamp = time();
$accessToken = $_SESSION["accessToken"];
$accessTokenSecret = $_SESSION["accessTokenSecret"];
$tweetText = trim($_POST["tweet"]);

$sigBase = "POST&" . rawurlencode($apiResourceUrl) . "&"
    . rawurlencode("oauth_consumer_key=" . rawurlencode($consumerKey)
    . "&oauth_nonce=" . rawurlencode($nonce)
    . "&oauth_signature_method=" . rawurlencode($oauthSignatureMethod)
    . "&oauth_timestamp=" . $oauthTimestamp
    . "&oauth_token=" . rawurlencode($accessToken)
    . "&oauth_version=" . rawurlencode($oauthVersion)
    . "&status=" . rawurlencode($tweetText));
$sigKey = rawurlencode($consumerSecret) . "&" . rawurlencode($accessTokenSecret); 
$oauthSig = base64_encode(hash_hmac("sha1", $sigBase, $sigKey, true));

OAuth POST transactions can (and are required to by Twitter) have the OAuth parameters included in a special Authorization HTTP header. It’s worth noting that besides the typical OAuth parameters, $sigBase also includes the API resource parameter status above. Non-OAuth parameters are needed in the signature but are excluded from the HTTP header. They are used in the POST body instead.

<?php
$authHeader = "OAuth oauth_consumer_key=" . rawurlencode($consumerKey) . ","
    . "oauth_nonce=" . rawurlencode($nonce) . ","
    . "oauth_signature_method=" . rawurlencode($oauthSignatureMethod) . ","
    . "oauth_signature=" . rawurlencode($oauthSig) . ","
    . "oauth_timestamp=". rawurlencode($oauthTimestamp) . ","
    . "oauth_token=" . rawurlencode($accessToken) . ","
    . "oauth_version=" . rawurlencode($oauthVersion); 

$httpPostDataUrl = "status=" . $tweetText; 

$context = stream_context_create(array("http" => array(
    "method" => "POST", 
    "header" => "Content-Type: application/x-www-form-urlencodedrnAuthorization: " . $authHeader . "rn", 
    "content" => $httpPostDataUrl)));

$result = file_get_contents($apiResourceUrl, false, $context);

If everything went smoothly you should have just posted to twitter on behalf of an authorized user. Twitter sends the success or failure status along with a very large amount of information regarding the transaction, which you can with print_r(json_decode($result)) if you like.

Summary

Now that you have a fair understanding of how Oauth works, implementing a third party library or troubleshooting OAuth in general should be a lot easier. In summary, you’ve learned how to:

  • Create a new Twitter application and obtain the Consumer Credentials
  • Obtain the Request Credentials which are necessary for requesting Access Credentials
  • Authorize your application with a user and obtain Access Credentials
  • Post a tweet on another user’s behalf using the Access Credentials

Today some of the most popular web applications provide access to an API – Flickr, Facebook, foursquare, Netflix, Last.fm, and GetGlue to name a few. Having an intimate knowledge of how to seamlessly communicate with these applications is a very desirable skill! Some of what you have learned here regarding the hashing of signatures and exchange of tokens can also be well applied to non-Oauth v1.0 APIs, such as Flickr’s pre-OAuth interface and the much easier to understand OAuth v2. Good luck and have fun!

Code for this series can be found on GitHub.

Image via Photosani / Shutterstock

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