A growing number of APIs support OAuth, i.e. it is possible to give service A access to service B without giving B’s username/password to A. In this article I’m going to show you how to use OAuth-enabled APIs with CakePHP (and the OAuth consumer component I have written).
First, there are some preparations necessary, namely the download of the required files:
- Get the OAuth component and place its content in “app/controllers/components”
- Get the OAuth library and put it in “vendors/OAuth”
- Set the security level in app/config/core.php to “low” (thanks to Bryan Young for mentioning in the comments)
The next step is to register your application at the service provider (e.g. Yahoo’s Fire Eagle) to get consumer key and consumer secret. Those values are then stored in a class called FireEagleConsumer if we go on using Fire Eagle as example service provider in this article:
// app/controllers/components/oauth_consumers/fire_eagle_consumer.php
class FireEagleConsumer extends AbstractConsumer {
public function __construct() {
parent::__construct('THE KEY', 'THE SECRET');
}
}
This class is then used by the component to access consumer key and secret.
Using an OAuth-enabled API consists of four steps:
- Get RequestToken
- Authorize RequestToken
- Exchange RequestToken for AccessToken
- Access the API using the AccessToken
In the ideal case the first three steps are performed once. But it is also possible that for example the service provider expires the AccessToken after some time, and so those steps have to be repeated.
Anyway, let’s have a look at how those steps look in code. We start with getting the RequestToken:
// app/controller/oauth_consumer_example_controller.php
class OauthConsumerExampleController extends AppController {
public $uses = array();
public $components = array('OauthConsumer');
public function index() {
$requestToken = $this->OauthConsumer->getRequestToken('FireEagle', 'https://fireeagle.yahooapis.com/oauth/request_token');
$this->Session->write('requestToken', $requestToken);
}
}
The code is probably self-explanatory, we have to add the component to the $components array, and then we get the RequestToken from the specified url (while writing this I just realized it would make sense to move the url to the FireEagleConsumer class…).
The next step is simple: we have to redirect the user to the authorize page of the service provider:
// app/controller/oauth_consumer_example_controller.php
class OauthConsumerExampleController extends AppController {
public $uses = array();
public $components = array('OauthConsumer');
public function index() {
$requestToken = $this->OauthConsumer->getRequestToken('FireEagle', 'https://fireeagle.yahooapis.com/oauth/request_token');
$this->Session->write('requestToken', $requestToken);
$this->redirect('http://fireeagle.yahoo.net/oauth/authorize?oauth_token='.$requestToken->key);
}
}
After the RequestToken is authorized, we get redirected to a callback url we specified while registering the application. We can now exchange the authorized RequestToken for an AccessToken:
// app/controller/oauth_consumer_example_controller.php
class OauthConsumerExampleController extends AppController {
public $uses = array();
public $components = array('OauthConsumer');
...
public function callback() {
$requestToken = $this->Session->read('requestToken');
$accessToken = $this->OauthConsumer->getAccessToken('FireEagle', 'https://fireeagle.yahooapis.com/oauth/access_token', $requestToken);
}
}
In a real use case you would also save the data of the AccessToken (key and secret) to the database, so you don’t have to perform all those steps every time you want to call the API.
The last step is to call the API, in this example to get the latest location of the user:
// app/controller/oauth_consumer_example_controller.php
class OauthConsumerExampleController extends AppController {
public $uses = array();
public $components = array('OauthConsumer');
...
public function callback() {
$requestToken = $this->Session->read('requestToken');
$accessToken = $this->OauthConsumer->getAccessToken('FireEagle', 'https://fireeagle.yahooapis.com/oauth/access_token', $requestToken);
$data = $this->OauthConsumer->get('FireEagle', $accessToken->key, $accessToken->secret, 'https://fireeagle.yahooapis.com/api/0.1/user');
// do something with the data
}
}
That’s it. Feedback is welcome!
Update 2008-09-15: Slightly adapted for new version of the component.
Update 2009-01-14: Adding hint about security level.

This is great, thanks Daniel.
Just a few weeks ago I thought, that it would be really great if there was a OAuth Component in CakePHP.
I will try this one out as soon as i can.
Have you also experimented with enabling a cakePHP-app as a OAuth-provider? I tried but failed horribly ;-)
+1 to Andreas’s request CakePHP app as an OAuth provider would be great!
@Andreas, Tarique: Thanks for your comments!
Yes, I’m experimenting with enabling a CakePHP app to be an OAuth provider and I hope I can write about it soon ;-)
[...] first is a component for CakePHP for accessing services with OAuth called OAuth component for CakePHP (points for [...]
Daniel, thanks for the great OAuth tutorial. You may want to mention somewhere in your article that the security level in /config/core.php needs to be set to ‘low’ to make this work.
@Bryan: Thanks for the hint, I added your hint to the article!
Thanks for the great tutorial!
It worked just fine for Fire Eagle, but when I tried getting a request token from myspace, who also has OAuth for their applications, it returned a null $requesToken after calling getRequestToken() and passing in the proper parameters. Should the code be any different between providers?
@Justin: Did you use a network analyzer like Wireshark to analyze what’s going on? And do you use the correct HTTP method to request the request token?
I’ve been trying to set this up using plugins but seems like the oauth consumer cannot find the consumer files.
It throws an error on line 69 because it’s searching for the main app component folder.
Is this a handicap or am I doing something wrong?
Actually I changed line 59 to this
$CONSUMERS_PATH = dirname(__FILE__).DS.’oauth_consumers’.DS;
and it now works in the plugin except I’m having a null accessToken…
was it me :|
@Rui: The issue with not finding the consumer files is definitely a bug, I didn’t think about plugins at the time I developed it. I have to fix this.
Regarding the second issue, it is difficult to say what could be the problem. Did you use a tool like Wireshark to see what’s going on?
@cakebaker: If you change your line 59 to what it posted it will work.
The rest was me being lazy and not setting the security level on cake to low.
It seem to work ok now.
BTW why not post your component on github or something?
@Rui: Ok, the bug is now fixed. And I’m glad the other problem disappeared :)
The component is already available on github: http://github.com/cakebaker/oauth-consumer-component/. However, I didn’t have linked to it yet ;-)
@cakebaker: Tip, how about another article using Gdata? :)
@Rui: Good idea, though I don’t have used Gdata yet ;-)
I know this article was written back in September but I just found it and am having problems. First, writing the requestToken Object to the Session is getting destroyed by Cake once the redirect has happened. Is anyone else having this issue? I am trying to do this with Twitter and I can get Twitter to allow my application but once it redirects to my callback url, there is no token to read, so I can’t get the access token. Any help would be really appreciated.
@Ryan: Thanks for your comment!
Hm, what’s the setting of “Security.level” in app/config/core.php? Can you set it to “medium” or “low”, and try again?
Hope that helps!
Security level is set to low. I have tried changing Session.start to false and manually creating my session but that didn’t seem to help. I have Session.save set to database, so I can see that it is writing the token to Session, but then it creates a new session once I return from Twitter.
@Ryan: You mention you set “Session.save” to “database”. Does it work if you keep the default value (”php”)?
No it didn’t work then either. I don’t know if that is tied into the cookies being saved as CAKEPHP and PHPSESSID, I haven’t tried that yet.
@Ryan: Hm, at the moment I don’t have any idea what could be the problem… I currently use it with Twitter in NoseRub, without any problem so far.
I’m running Cake 1.2.2.8120 and I’m getting the error:
Fatal error: Class ‘OAuthConsumer’ not found in (…)/controllers/components/oauth_consumers/abstract_consumer.php on line 40
Sorry, I just didn’t put the library into the vendors directory when I thought I had… Feel free to delete this and the last comment!
@psuedo: No problem, I hope it works now as expected!
Does anyone know how to import contacts from Gmail, yahoo hotmail using this?
The example is very basic but a good example to start off with.
Thanks
@Jerry: At least if the services you mention provide an OAuth-enabled API it should work in a similar way as shown in the example: you have to get an access token and with that access token you can then access the respective API. Or did you encounter a specific issue?
Hi David,
Iam trying to connect to google docs api using this component.. however, I get an error saying
“parameter_absent oauth_parameters_absent:scope ”
The code Im using is as follows:
Because of this I cannot seem to get past the first step of this tutorial ;)
Ever run across this?
thanks
Fixed… our server time was off.
@Keith: Good to hear you could fix the issue in the meantime :)
You don’t have an example of using a previously stored access token. This would be greatly appreciated as it is not clear to me at all how to do this, nor have I seen or heard of anyone doing this with a site like, let’s say Twitter. Is it possible, or are you just pointing out how to use a preexisting library of code? Because as actual solutions go, this one isn’t fully realized.
@J. Adam: Thanks for your comment!
Well, usually an access token is represented by a model, and so you retrieve it with something like $this->AccessToken->find(’first’, some criteria); And with those data you can then call the respective API as shown in the article, simply replace $accessToken->key and $accessToken->secret with the data you got from your model.
Hope that helps!