Twitter API, OAuth Authentication, and Zend_Oauth Tutorial

* 06/2014 UPDATE
Thanks to Ivan for pointing out that the siteUrl is now ‘https://api.twitter.com/oauth’. Make sure to use this new value anywhere where the siteUrl is mentioned below.

I recently had to work on a project that required me to interact with the Twitter API. I had done this before so I wasn’t expecting anything different until I remembered that Twitter had changed their API to start using OAuth for authentication. If you are not familiar with OAuth, it’s a secure way of authenticating without requiring a user to submit their username and password to third-parties – you can read more about it atย OAuth. There are lots of resources online that talk about this in detail but I wasn’t able to find one that explained the entire process in a way that made sense. Hopefully this post will give you everything you need to get started with the Twitter API. I’m going to go through the steps required to make this work without using the entire zend framework.

Objective

This tutorial will go step-by-step in explaining how to create a small PHP application that can interact with the Twitter API. Our goal is to:

  • Authenticate
  • Display our latest tweets
  • Post new tweets from PHP
  • Display the last few times our account was mentioned

The only assumptions at this point (other than knowing PHP) is that you have a twitter account and the zend framework library downloaded. We won’t be using the entire framework, just some of the files as standalone modules.

Registering An App

The first step in being able to communicate with the Twitter API is to register an app in their system so you can receive all the necessary keys to authenticate with OAuth. Go to dev.twitter.com and log in with your Twitter account. Now click on ‘register an app’ (if that link is not visible then click on ‘your apps’ on the top right and then click on ‘register an app’ in the next page). These are the values I put in the form on the next page for my app. Feel free to follow along. I’ll explain the important inputs.

Application: Joey’s Blog Example
Description: Twitter PHP App
Application Website: http://www.joeyrivera.com
Organization: None
Application Type: Browser
Callback URL: http://www.joeyrivera.com/twitter/callback.php
Default Access Type: Read & Write

Most of the above are self-explanatory but let me explain callback since it’s an important one. Before we can talk to Twitter, we need to authenticate to get a token from Twitter. Once we have our token, we can start calling the API. During authentication, we are actually going to leave our application and go to Twitters website where the user will have to enter their twitter credentials. After the user allows our application and is done authenticating, Twitter will redirect the user back to our applications callback url. We haven’t created the file yet, but point back to a file called ‘callback.php’ where you plan on putting this file. We will create this file later. (I mentioned users don’t have to give third-parties their user/pass but they still have to let Twitter know it’s ok for this app to access their account.)

Enter the captcha and register. At this point we have successfully registered our app that can now start communicating with the Twitter API.

Authenticating

To authenticate using Zend_Oauth we need to create a consumer object. The consumer needs an array with the following parameters:

  • callbackUrl: Same as the one used during ‘registering an app’.
  • siteUrl: The url where the token request will take place. In this case: ‘http://twitter.com/oauth’.
  • consumerKey: This value is assigned to you after registering your app. To get this value, log into dev.twitter.com, go to your apps, and select the app you just created during ‘registering an app’ above. All your keys/secret and info will be listed on that page.
  • consumerSecret: same steps as consumerKey.

We are going to be using the code from zend docs with a couple minor tweaks or additions. The code is below:

authenticate.php

session_start();

set_include_path('/path/to/zend/library/1.10.8');
require 'Zend/Oauth/Consumer.php';

$config = array(
    'callbackUrl' => 'http://www.joeyrivera.com/twitter/callback.php',
    'siteUrl' => 'http://twitter.com/oauth',
    'consumerKey' => 'ASD234ADF34ADSF',
    'consumerSecret' => '24GH789JSDFGDFG345098DF09873SDFSD'
);

$consumer = new Zend_Oauth_Consumer($config);

// fetch a request token
$token = $consumer->getRequestToken();

// persist the token to storage
$_SESSION['TWITTER_REQUEST_TOKEN'] = serialize($token);

// redirect the user
$consumer->redirect();

Create a file and paste the above code in there and save your file as authenticate.php. Go back and modify the values of the $config array to use your callbackUrl, siteUrl, consumerKey, and consumerSecret. Also make sure to modify the include path to include your library folder where the zend framework resides (I’m using the framework version 1.10.8 for these examples).

Quick explanation of the code. First we start our session since we’ll be using a session variable to track the request token needed to create the access token later. Then we create a consumer and create the request token. Finally we call redirect on the consumer which sends us to twitter feeding it all the necessary information in the proper format for us to then authenticate. There is lots of magic going on behind the scene and for a better understanding on how the token and signature works read the OAuth docs. I personally find it much easier to use Zend_Oauth instead.

Now lets create the callback file, code is below:

callback.php

session_start();

set_include_path('/path/to/zend/library/1.10.8');
require 'Zend/Oauth/Consumer.php';

$config = array(
    'callbackUrl' => 'http://www.joeyrivera.com/twitter/callback.php',
    'siteUrl' => 'http://twitter.com/oauth',
    'consumerKey' => 'ASD234ADF34ADSF',
    'consumerSecret' => '24GH789JSDFGDFG345098DF09873SDFSD'
);

$consumer = new Zend_Oauth_Consumer($config);

if (!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN']))
{
    $token = $consumer->getAccessToken($_GET, unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));

    // Now that we have an Access Token, we can discard the Request Token
    $_SESSION['TWITTER_REQUEST_TOKEN'] = null;
} else {
    // Mistaken request? Some malfeasant trying something?
    exit('Invalid callback request. Oops. Sorry.');
}

// save token to file
file_put_contents('token.txt', serialize($token));

Save this file as callback.php after modifying the $config variables and library path just like with authenticate.php. We are once again starting our session to be able to capture the ‘TWITTER_REQUEST_TOKEN’ created in the previous step. Then we create the consumer again and check to make sure the session is there and that we received query string parameters from Twitter. If everything is as expected, we feed the consumer all the information and ask it for an access token. This is the token we need to track since it’s the token we need for any call our application makes to the Twitter API. Since we no longer need the request token, we can remove it from the session.

The last step is to save the token somewhere so we can reuse it and not have to authenticate again. Twitter’s access token does not expire (at least not now). This means, once we authenticate with Twitter, as long as we have our access token stored and accessible to us, our client will not have to authenticate again (assuming Twitter doesn’t change their mind later and adds an expiration to their tokens). For the purpose of this example, I’m storing this token in the file system. Another option is to store this value in the database, it’s really up to you where you want to put it. If you are saving it to the file system, make sure that file is writable by your application.

Both files are created so lets try it out. Go to your browser and access the authenticate.php file. When the page loads, you should be redirected to Twitter and asked to log in (unless you are already logged into Twitter). Enter your twitter account user/pass that you want to access and continue. Next you’ll be asked if you want to allow this application to access your account. Go ahead and click allow, then you’ll be taken to your callback.php url. At this point we have authorized, received our access token, and stored it. Now we are done with our first goal and ready for the good stuff.

Using our Token

Our next goal was to display our latest tweets so this will be our first example on how to use our token. Technically, this isn’t the best example as you don’t need to authenticate with Twitter to display public user tweets but you’ll still get to see how to make a call to the Twitter API using our token.

show_tweets.php

set_include_path('/path/to/zend/library/1.10.8');
require 'Zend/Oauth/Consumer.php';

$config = array(
    'callbackUrl' => 'http://www.joeyrivera.com/twitter/callback.php',
    'siteUrl' => 'http://twitter.com/oauth',
    'consumerKey' => 'ASD234ADF34ADSF',
    'consumerSecret' => '24GH789JSDFGDFG345098DF09873SDFSD'
);

$token = unserialize(file_get_contents('token.txt'));

$client = $token->getHttpClient($config);
$client->setUri('http://twitter.com/statuses/user_timeline.json');
$client->setMethod(Zend_Http_Client::GET);
$client->setParameterGet('screen_name', 'joeyrivera');
$client->setParameterGet('count', '10');
$response = $client->request();

$tweets = json_decode($response->getBody());

foreach($tweets as $tweet)
{
	echo $tweet->text, "<br>";
}

Paste the above code into a file called show_tweets.php and edit the configs yet again plus the library. At this point I’ll stop mentioning to edit the config and library – just remember to do the same with the next couple examples. First we get our token which we saved to a file during the callback phase. Then we create a client object, tell it what url to call, the method to use and pass two params to let the API know who’s tweets we want and how many tweets to return. Finally we tell the client to initiate the request and we display it when it comes back.

Where did I get the uri from? from Twitters docs page. Spend some time there learning all the different methods you can call and what the required parameters are. For user_timeline (which is what we want to get our latest tweets) we need to call the uri used above. The last part, the .json at the end tells Twitter that we want a JSON encoded response back which is why we need to do a json_decode on the body to view it. You could have used .xml if you wanted an xml back instead. The docs for user_timeline also specify you need to do a get which is why we set it as a method and add the two get parameters. There are more parameters you can set if you like.

This is what I see when I run this page with my screen name:

Flash, jQuery, and Php - what a pain you have all been to me today but I'm glad all is well again.
Put my car up on autotrader, check it out if you are in the market for a 2005 Subaru WRX STi or know someone who might: http://is.gd/g3tqv
someone owns a image rollover patent? http://arstechnica.com/tech-policy/news/2010/10/patent-troll-takes-over-the-web-can-it-be-stopped.ars
Microsoft has the best commercials! http://holykaw.alltop.com/microsoft-pokes-fun-at-smartphone-users-in-ne
Finally got oAuth working to post to Twitter from PHP.
Accidentally found this very cool video by RefinedData http://refineddata.com/products/refinedtraining/index.php
You guys have recommendations on course authoring tools like articulate/captivate that don't have a player. Just a place to create content?
Cool story on YouTube instant http://www.feross.org/youtube-instant-media-frenzy/ Congrats to Feross on the accomplishment.
After driving a Z06 Corvette, I have become a believer of American muscle. STi was fun but just doesn't compare to a Z06.
Been week since we paid for Adobe developer support license and we are still not closer to solving our problem. Hoping to make progress soon

Now lets submit a tweet.

submit_tweet.php

set_include_path('/path/to/zend/library/1.10.8');
require 'Zend/Oauth/Consumer.php';

$config = array(
    'callbackUrl' => 'http://www.joeyrivera.com/twitter/callback.php',
    'siteUrl' => 'http://twitter.com/oauth',
    'consumerKey' => 'ASD234ADF34ADSF',
    'consumerSecret' => '24GH789JSDFGDFG345098DF09873SDFSD'
);

$token = unserialize(file_get_contents('token.txt'));

$client = $token->getHttpClient($config);
$client->setUri('http://twitter.com/statuses/update.json');
$client->setMethod(Zend_Http_Client::POST);
$client->setParameterPost('status', 'I hope to get my blog post on Twitter API with Zend_Oauth up in the next day.');
$response = $client->request();

$data = json_decode($response->getBody());
echo $data->text;

The code is very similar. The resource we want to call this time is statuses/update. It requires a post method so we use POST and setParameterPost instead of GET. The one required param is status – set that to the string you want to tweet and run this page. Now go check your tweeter account and you should have that status show up. Make sure the string you pass is 140 characters or less. Also, twitter won’t allow you to submit two identical statuses so if you are testing this code and it’s not working, make sure you are sending a unique string.

Finally we’ll create one last example that displays the last 5 mentions of our twitter account.

mentioned_tweet.php

set_include_path('/path/to/zend/library/1.10.8');
require 'Zend/Oauth/Consumer.php';

$config = array(
    'callbackUrl' => 'http://www.joeyrivera.com/twitter/callback.php',
    'siteUrl' => 'http://twitter.com/oauth',
    'consumerKey' => 'ASD234ADF34ADSF',
    'consumerSecret' => '24GH789JSDFGDFG345098DF09873SDFSD'
);

$token = unserialize(file_get_contents('token.txt'));

$client = $token->getHttpClient($config);
$client->setUri('http://twitter.com/statuses/mentions.json');
$client->setMethod(Zend_Http_Client::GET);
$client->setParameterGet('count', '5');
$response = $client->request();

$tweets = json_decode($response->getBody());

foreach($tweets as $tweet)
{
	echo $tweet->text, "<br>";
}

The mentions resource uses GET and doesn’t require any parameter. I’m passing a count of 5 so you don’t get too much back. Here is what I see when I run this page:

heads up! @mosesngone and @joeyrivera consuming Web Services Nov 4th @atlantaphp #atlantaphp http://meetu.ps/3Rbt

Conclusion

Using Zend_Oauth it’s really easy to authenticate with OAuth and track your token. At that point calling the Twitter API is very simple. I want to thank the guys at Zend for making our lives so much easier with all these great modules. If you have any question feel free to ask. Hopefully you have all found this post very informative and helpful.

EDIT: Here is a similar post on using Facebooks Graph API with their PHP SDK

32 thoughts on “Twitter API, OAuth Authentication, and Zend_Oauth Tutorial”

  1. Oh great post . I too was developing a twitter client with zf ( Just a personal project to learn oauth ๐Ÿ˜‰ ). I was stuck in the middle which I was getting a Zend_Rest_Client object when I used $twitter->friendsTimeline() .
    I loved to get a json was wondering how to get it. Your post helps me to resolve the issue.
    Thanks .

  2. Hari, I’m glad this post was able to help you out.

    Rahul, funny you mention facebook since I’m about to write another post just like this one but for facebook in the next few days or week to prepare for my Web Services talk coming up.

  3. Maybe not such a great idea to post your OAuth details on your blog so everybody can start abusing the API on your behalf… ๐Ÿ˜Ž

    Unless of course you already deleted your api registration at twitter. Did not test it ๐Ÿ™‚

    1. I used fake values for all of it. The key/secrete/and callback url are all fake but wise words for people writing posts like these – make sure not to use your real info.

  4. I did exactly same as you said on this site. But I get the error messege as follows:

    Fatal error: Call to a member function getHttpClient() on a non-object in (file path) on line 14

    The line 14 I have is, line14 => $client = $token->getHttpClient($config);
    Please, help me if you know why I get this error. Thanks!

    1. Suk, how are you saving your token when you get it and how are you loading it? Also, are you still including the consumer.php file and the file path to the zend library in the step where you are getting this error? Finally, the token is being unserialized before you make this call correct?

  5. Got the same issue, my knowledge is limited but I followed every step of your tutorial, the authentication.php->Twitter->callback.php seems to work but when trying e.g. submit_tweet the mentioned error occure. Regarding the token, is it supposed to be stored in a txt? It doesent seem to be, I tried to rewrite so it stores in a cookie but didnt made it, hope I can get some help cuase I think I am really close.


    null:

    I did exactly same as you said on this site. But I get the error messege as follows:
    Fatal error: Call to a member function getHttpClient() on a non-object in (file path) on line 14
    The line 14 I have is, line14 => $client = $token->getHttpClient($config);
    Please, help me if you know why I get this error. Thanks!

    1. Josub,

      Could you answer the questions I asked Suk? Also, like you mentioned, in my example I save the token to a file. When I open the file, I can see all the contents of the token in it. When you open your file, do you see anything in there? Does your application have access to write to that file?

      1. The file is empy, it is in the same diretory as the twitter-files. It has permission 666, is there anything else I might have missed?

        1. Can you try writing something to the file in php – file_put_contents(‘file.txt’, ‘asdf’); to see if the problem is that you can’t write to the file. If you can then the problem might be that you aren’t getting a token back. Also, make sure you have error messages turned on in case something is throwing an error. Put error_reporting(-1); at the top of your php file.

          1. I tried file_put_contents(โ€˜file.txtโ€™, โ€˜asdfโ€™); but it didnt write in token.txt. I have permission 666 is that ok?

          2. Maybe your directory doesn’t allow access to the file? You could try saving the token to the database instead and see if that works better?

          3. Ok thanks for the help I will try that, do you think the errormsg regarding getHttpClient() will solve or is it due to something else? I guess it is something on my machine though since other people got the script to work.

  6. I’m getting the following exception from ZF: Authorized token from Service Provider does not match supplied Request Token details. Any idea what could be the problem?

    1. Jonathan, how are you storing and loading your token? If I remember correctly, I had this same issue when I printed the token to the screen, copy/pasted it to a db field and tried to use it. Because of formating and special characters, that token was no longer valid so I had to in code save my token directly to the db and then it worked.

  7. Great post Joey!

    I was trying to do this for too many hours and you gave me the key for my app. I stored the access token unserialized and tried to use it after in the same format. But got the same error that Josub and Suk mentioned “Call to a member function getHttpClient() on a non-object”. I think its because the Zend_Oauth_Token_Access object is into the serialized token right?

    Anyway, thanks a lot and congratulations for your useful Blog.

  8. Awesome post joey!!!

    The documentation that is currently present on the zend website is just awfull, and this helped me out no end!

    Keep them coming mate !

    Del

  9. Hi,

    I am calling my call back controller and getting this error:

    Uncaught exception ‘Zend_Oauth_Exception’ with message ”http://www.marcelodsalvador.com/oauth/callback’ is not a valid URI’

    any help would be appreciated =)

    Marcelo

Leave a Reply

Your email address will not be published. Required fields are marked *