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
.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
.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
<?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));
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.
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.
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.