Goodreads Developers discussion
OAuth setup with PHP
date
newest »

message 1:
by
Scott
(new)
Aug 18, 2009 05:10PM

reply
|
flag

Here's some OAuth examples in PHP, but not specific to Goodreads..
http://code.google.com/p/oauth-php/



get a request token: /oauth/request_token
authorize the request token: /oauth/authorize
exchange for access token: /oauth/access_token
We're using OAuth 1.0. You should use HMAC-SHA1 for signing and send parameters as the value for the Authorization header as described here:
http://oauth.net/core/1.0/#auth_header
You'll probably want to use a library to do the signing. There's code here for PHP here and I'm sure there are other projects as well: http://oauth.net/code


Any tips???
PS Much of the OAuth class is from the Twitter OAuth Class (Very very well programmed!!)
Class
-----
$key='XXXXXXXXXX';
$secret='XXXXXXXXXXXX';
require_once 'OAuth.php';
class Good{
function __construct($key, $secret, $oauth_token=NULL, $oauth_token_secret=NULL){
$this->consumer = new OAuthConsumer($key, $secret);
}
function AuthoriseURL($token){if(is_array($token)){
return 'http://www.goodreads.com/oauth/author...}}
function go($url){return header('Location: '.$url);}
function http($url, $post_data = null){
$ch = curl_init();
if(defined("CURL_CA_BUNDLE_PATH")){curl_setopt($ch, CURLOPT_CAINFO, CURL_CA_BUNDLE_PATH);}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if (isset($post_data)){curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);}
$response = curl_exec($ch);
$this->http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->last_api_call = $url;
curl_close ($ch);
return $response;}
function oAuthParseResponse($responseString) {
$r = array();
foreach(explode('&', $responseString) as $param){
$pair = explode('=', $param, 2);
if (count($pair) != 2){continue;}else{$r[urldecode($pair[0:])] = urldecode($pair[1:]);}
}return $r;}
function getRequestToken(){
$this->response = $this->oAuthRequest('http://www.goodreads.com/oauth/reques...
return $this->oAuthParseResponse($this->response);
}
function getAccessToken($token = NULL) {
$this->response = $this->oAuthRequest('http://www.goodreads.com/oauth/access...
$token = $this->oAuthParseResponse($this->response);
$this->token = new OAuthConsumer($token['oauth_token':], $token['oauth_token_secret':]);
return $token;}
function oAuthRequest($url, $args = array(), $method = NULL) {
if (empty($method)) $method = empty($args) ? "GET" : "POST";
$req = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $args);
$req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $this->consumer, $this->token);
switch ($method) {
case 'GET': return $this->http($req->to_url());
case 'POST': return $this->http($req->get_normalized_http_url(), $req->to_postdata());
}
}
function setToken($token){$this->token=$token;}
} //class
Example
-------
$g=new Good($key,$secret);
if(!isset($_REQUEST['oauth_token':])){
$tok=$g->getRequestToken();
$g->go($g->AuthoriseURL($tok));
}else{
//Not sure of this bit
$acc=$g->getAccessToken($_GET['oauth_token':]);
print_r($acc);
}

http://twitter.abrah.am/
Hope this helps!
(some of the html isn't showing as code, but I think you get the idea)
<?php
// require twitterOAuth lib
require_once('../twitterOAuth.php');
/* Sessions are used to keep track of tokens while user authenticates with twitter */
session_start();
/* Consumer key from twitter */
$consumer_key = '';
/* Consumer Secret from twitter */
$consumer_secret = '';
/* Set up placeholder */
$content = NULL;
/* Set state if previous session */
$state = $_SESSION['oauth_state':];
/* Checks if oauth_token is set from returning from twitter */
$session_token = $_SESSION['oauth_request_token':];
/* Checks if oauth_token is set from returning from twitter */
$oauth_token = $_REQUEST['oauth_token':];
/* Set section var */
$section = $_REQUEST['section':];
/* Clear PHP sessions */
if ($_REQUEST['test':] === 'clear') {
session_destroy();
session_start();
}
/* If oauth_token is missing get it */
if ($_REQUEST['oauth_token':] != NULL && $_SESSION['oauth_state':] === 'start') {
$_SESSION['oauth_state':] = $state = 'returned';
}
/*
* Switch based on where in the process you are
*
* 'default': Get a request token from twitter for new user
* 'returned': The user has authorize the app on twitter
*/
switch ($state) {
default:
/* Create TwitterOAuth object with app key/secret */
$to = new TwitterOAuth($consumer_key, $consumer_secret);
/* Request tokens from twitter */
$tok = $to->getRequestToken();
/* Save tokens for later */
$_SESSION['oauth_request_token':] = $token = $tok['oauth_token':];
$_SESSION['oauth_request_token_secret':] = $tok['oauth_token_secret':];
$_SESSION['oauth_state':] = "start";
/* Build the authorization URL */
$request_link = $to->getAuthorizeURL($token);
/* Build link that gets user to twitter to authorize the app */
$content = 'Click on the link to go to twitter to authorize your account.';
$content .= '
'.$request_link.'';
break;
case 'returned':
/* If the access tokens are already set skip to the API call */
if ($_SESSION['oauth_access_token':] === NULL && $_SESSION['oauth_access_token_secret':] === NULL) {
/* Create TwitterOAuth object with app key/secret and token key/secret from default phase */
$to = new TwitterOAuth($consumer_key, $consumer_secret, $_SESSION['oauth_request_token':], $_SESSION['oauth_request_token_secret':]);
/* Request access tokens from twitter */
$tok = $to->getAccessToken();
/* Save the access tokens. Normally these would be saved in a database for future use. */
$_SESSION['oauth_access_token':] = $tok['oauth_token':];
$_SESSION['oauth_access_token_secret':] = $tok['oauth_token_secret':];
}
/* No form submitted, present it here */
if (empty($_REQUEST['shelfname':])) {
$content = "" .
"" .
"";
/* We got our form submit, process it */
} else {
/* Create TwitterOAuth with app key/secret and user access key/secret */
$to = new TwitterOAuth($consumer_key, $consumer_secret, $_SESSION['oauth_access_token':], $_SESSION['oauth_access_token_secret':]);
$content = $to->OAuthRequest('http://www.goodreads.com/shelf.xml', array('name' => $_REQUEST['shelfname':],), 'POST');
}
break;
}
?>
Twitter OAuth in PHP
Welcome to a Twitter OAuth PHP example.
This site is a basic showcase of Twitters new OAuth authentication method. Everything is saved in sessions. If you want to start over ?test=clear'>clear sessions.
Get the code powering this at http://github.com/abraham/twitteroauth
Read the documentation at https://docs.google.com/View?docID=dcf2dzzs_2339fzbfsf4
<?php print $content; ?>

After you send the user to goodreads.com to authorize the request token, if they authorize your app they'll be redirected to your callback URL with the oauth_token param. You'll then make a separate request to exchange the (now authorized) request token for an access token. The body of the response from /oauth/access_token will contain the access token oauth_token and oauth_token_secret as form encoded parameters.
So first you'll get the request token with getRequestToken(). Then you'll send the user to AuthorizeURL. Then when we redirect the user to your callback, you'll call getAccessToken(). (The oauth_token param that's in the callback URL will contain the token of your request token. You can use to verify it matches yours.) Does that make sense?
Ben

Firstly WOOHOOOO
$to = new Good($key, $secret, $_SESSION['oauth_access_token':], $_SESSION['oauth_access_token_secret':]);
$content = $to->OAuthRequest('http://www.goodreads.com/api/auth_user', array(), 'GET');
print_r($content);
<?xml version="1.0" encoding="UTF-8"?>
true
I have a working PHP framework.
But..... quicky message to all developers
you MUST use Sessions to cache the original request token!!!
Let me do a bit more testing first.


All of these steps that you went through to get an access token will be the same for any OAuth provider. I.e., the code you wrote to ask for request token, get it authorized, and then exchange for an access token will probably work as is with any site that supports OAuth, assuming their endpoints are the same.
We'll work on making this more clear or at the very least linking to a site that does a good job of explaining it. OAuth can be a little tricky to worth with as a dev, but hopefully as adoption improves so will the tools and example code.

Let me do a bit more refinement and I'll package up what I've done. Although I am busy prep'ing my own site for release in the next week.
But spot on .. looks good so far..
PS Can we have access to information in other formats other than RSS. ie JSON, XML.
ie
http://twitter.com/statuses/update.json
(to get the information in json format)
http://twitter.com/statuses/update.xml
or xml

I'm using the twitter.abrah.am PHP library and it works great on Windows. However, when I use it on CentOS, twitter gives me a null oauth_token ($token['oauth_token':] is null, blank)...
what could be going wrong? Am I forgetting to do something special with CentOS. I would really appreciate any kind of help here...
thanks in advance :)

Maybe a library is missing, or is out of date?
Hard to say, but you might have better luck asking the guy who wrote it.

Then I looked in the library, and it says:
public static $TO_API_ROOT = "https://twitter.com";
then I did: wget https://www.twitter.com
and it said that it didn't trust the certificate and that I should use --no-check-certificate
so I included what it told me and after that it let me download the .html file
So! I wonder if there's any kind of issue related to https. I remember that on installation, I only enabled the HTTP port on FW, not HTTPS.
Maybe is that? now, how do I enable the HTTPS port :D?
Thank you very much


This was a very useful thread for me, so thank you. Still, it took me a day and a half to get goodreads and OAuth working correctly with PHP.
To save this pain for anyone else, I've uploaded the working code to a google project page:
http://code.google.com/p/goodreads-oa...
To the Goodreads dev team, feel free to point to this code as an example of goodreads interacting with PHP via OAuth. (or take the code and modify it if you want to make a better example!)
-Rob

http://twitter.abrah.am/ for a Goodreads to Feedbooks mashup (Bookshare: http://grlk.net/bs). The only thing I had to do other than what is shown above:
message 11: by Scott (last edited Oct 26, 2009 07:03am)
Oct 26, 2009 07:01am was to make sure that I followed my servers security rules about explicity specifying the directory sessions were stored in. If you are having trouble, you might take a look at your server's security settings. Also, remember, don't output any debugging info before setting cookies - the cookie has to be in the header.
From there I was able to use pretty much the same code with conditions to specify configuration settings for oAuth integration with Twitter as well.

I've used Rob's base to begin building an OAuth solution, however I can't use sessions. Where and how are the oauth_token and oauth_token_secret returned? My callback file is getting the token and authorize parameters, but I'm not sure what to do from there.
A few questions whose answers could help:
1) Can this even be done without sessions?
2) Where are the $_SESSION['oauth_token'] and $_SESSION['oauth_token_secret'] initially set and is there a way to override this?
Thanks,
Mike

Nevermind... figured it out. I had pulled the $_SESSION stuff into a separate file. Switched it all out for cookies and it's working great.
Thanks for the solid base of work, Rob!

There are precompiled oAuth libraries available here which are kept quite to date: http://windows.php.net/downloads/pecl...
Also you may have issues getting them to work with wamp since wamp is usually a few versions behind from the official release with php. You can follow this tutorial on how to manually add php versions to wamp: http://www.websanova.com/tutorials/ph...

After following README instructions, I'm getting:
This as sign in url:
http://www.goodreads.com/oauth/author...
and this by clicking sign in url:
There Was an Error with This Oauth Request
This is likely due to an expired request. Please notify the owner of the application if this error continues to happen.
Tested on:
Ubuntu 12.04.2 LTS (GNU/Linux 3.5.0-54-generic x86_64)
PHP 5.3.10-1ubuntu3.26 with Suhosin-Patch (cli)