Musings of ErisDS
beta
ErisDS

Having to include an entire PHP OAuth library every time I want to make a simple API request for some of my own data from a 3rd party app like Twitter really pisses me off. Perhaps this is unreasonable, but it’s a problem I ran into for the 4th or 5th time today when trying to help John O’Nolan fetch his status count for his blog.

Making a REST API request for your own twitter info using the “user/show” request is relatively simple as it doesn’t actually require authentication. That is until you upload the code to your server and discover that someone else sharing the server’s IP is very selfishly hogging all of the API requests.

Twitter very helpfully allows you to authenticate your own app for your account and generate an OAuth Access token, meaning you can skip the first few steps of the OAuth process. However after much Googling, I discovered there really aren’t that many examples of what to do next – they all seem to use one or another library – which seems totally unnecessary for making one request.

After much searching, finally I found one awesome step-by-step tutorial which explains the first few steps of OAuth and in particular how to build the OAuth HTTP headers and OAuth signature to sign the request. So I’ve taken lead from here, borrowed the helper functions and signature code, and put it all together to make a signed GET request to the API and return some ACTUAL data.

Here’s the couple of helper functions I borrowed, the first combines the request URI and parameters into a string as required by the OAuth signature. The second one takes an array of OAuth credentials/settings and combines them into the HTTP header for use with cURL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function buildBaseString($baseURI, $method, $params)
{
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    }
    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth)
{
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";
    $r .= implode(', ', $values);
    return $r;
}

Next you need to setup all of the OAuth credentials and settings. For Twitter, the tokens, keys and secrets you need will all be available on your App page. If you haven’t got any Apps, you’ll need to create one, authorise it for your account and grab an access token.

1
2
3
4
5
6
7
8
9
10
11
12
13
$url = "http://api.twitter.com/1/account/totals.json";

$oauth_access_token = "YOUR TOKEN HERE";
$oauth_access_token_secret = "YOUR TOKEN SECRET HERE";
$consumer_key = "YOUR KEY HERE";
$consumer_secret = "YOUR SECRET HERE";

$oauth = array( 'oauth_consumer_key' => $consumer_key,
                'oauth_nonce' => time(),
                'oauth_signature_method' => 'HMAC-SHA1',
                'oauth_token' => $oauth_access_token,
                'oauth_timestamp' => time(),
                'oauth_version' => '1.0');

The tricky bit, that doesn’t ever seem to be explained to well, is creating the OAuth signature. For HMAC-SHA1, this boils down to the following few lines:
Create your URI base string by combining the URL you will be sending the request to with the oauth details as per the helper function. The key is the consumer secret and access token secret URL encoded and combined with an ampersand. Finally, the base url and the composite key are hashed and and base 64 encoded. Sounds really fraking complicated when you read the instructions, doesn’t look so bad when it’s written out in PHP.

1
2
3
4
$base_info = buildBaseString($url, 'GET', $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;

To make the request we have to setup a HTTP header and a few other options to pass to cURL. The helper method does the hard work of creating the correct header format with the OAuth settings and then finally, it’s time to make the request with cURL.

1
2
3
4
5
6
7
8
9
10
11
12
13
$header = array(buildAuthorizationHeader($oauth), 'Expect:');
$options = array( CURLOPT_HTTPHEADER => $header,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$twitter_data = json_decode($json);

This works really well if you just want to fetch data from your own account – last statuses, mentions, favourites or your stats like in the example above. It should also work with any OAuth based API which supports HMAC-SHA1 signatures (Google, LinkedIn, Vimeo, the list goes on). If the API you’re working with doesn’t have a neat tool for getting an access token for your account like Twitter does, you can always do the first few authentication steps by using an online client. Fill out your details and it will handle the first few exchanges, and once you have your access token you’re free to make requests using just the 50 lines of code above, instead of requiring an OAuth library.

Download the full Twitter OAuth Code Example

Big Kudos to Jason Graves (aka. GodLikeMouse) for putting his excellent PHP OAuth tutorial on the web.

Related Posts

Share this...

  •  Add 'Twitter OAuth: Simple cURL requests for your own data' to Del.icio.us
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to Twitter
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to digg
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to FURL
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to reddit
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to Technorati
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to Newsvine
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to Stumble Upon
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to Google Bookmarks
  • Add 'Twitter OAuth: Simple cURL requests for your own data' to FaceBook

Comments

16 Comments to "Twitter OAuth: Simple cURL requests for your own data"
  1. Twitter OAuth: Simple cURL requests for your own data « Http « Php « Codes php – Share your php snippets

    27th Oct

  2. 10th Nov

    Kasper says:

    Great tutorial!
    I’ve actually read over 20 tutorials and this one was by far the easiest to use!
    Thank you very very much!

  3. 10th Nov

    Kasper says:

    Unfortunatly, for some reason it still doesnt work… The problem is, on my domain (with shared hosting -.- ) I can’t use the regular settings (read: no special settings) to get the user timelines from Twitter, because someone else on the same IP is maxing out the limit of requests. So I read that using OAuth would fix this. The problem is… it doesnt…
    Would you know how to fix this?

  4. 10th Nov

    ErisDS says:

    This was exactly the problem I was trying to get around. What request are you using to grab the data?

  5. 10th Nov

    Kasper says:

    Thanks for the fast reply!
    And yeah, it is exactly what I’m trying to get around aswell…
    I am requesting this url: http://api.twitter.com/statuses/user_timeline.json?screen_name=NS_online
    Using your method it works fine here: http://bit.ly/uWaf53
    But when I move that to the domain which is having problems, I get Http error 400: http://bit.ly/s9Gm9u
    Really weird, right?

  6. 10th Nov

    Kasper says:

    For the rest the code is exactly like yours…

  7. 10th Nov

    ErisDS says:

    Ok so the problem you have is, if you look here:
    https://dev.twitter.com/docs/api/1/get/statuses/user_timeline

    For that request it says “authentication: supported”. I had this problem too, I have no idea how to force twitter to use your authentication, and what it seems to do is ignore it even if you provide it.
    So what you will need to do is either find out how to force that request to use authentication, or use a different api request which has “authentication:yes” (there are many that do similar things)

  8. 10th Nov

    ErisDS says:

    Additional note. Try not specifying the screen name at all.. that might trick it into being an authenticated request – i.e. return the authenticated user’s details rather than the one you specify.

  9. 10th Nov

    Kasper says:

    Hmmm, I already suspected something like that… Too bad nobody responds to the Twitter Dev forum… (except you)

  10. 10th Nov

    Kasper says:

    At the moment I’ve partially fixed the problem, in my case atleast: I’ve now used the Search API, searching for all tweets from a certain user.
    However, this comes with a big downside: using the Search API, I can no longer see what the user replied to in his message…

  11. 11th Nov

    Kasper says:

    The whole problem is solved now, using the (extremely simple) tmhOAuth library (mentioned here: https://dev.twitter.com/discussions/3564 ) which you can get here: https://github.com/themattharris/tmhOAuth/

    The reason why your method doesnt work, is because (as far as I understand) there is no signature specified. There is a signature method, but not signature.

  12. 21st Mar

    kermit says:

    Great! after a day spent on twitter oauth I’ve found this page.. and all problem with that f** oatuh signature was solved!
    thanks.

  13. API Twitter e Oauth | Zenworks

    21st Mar

  14. 23rd Apr

    Boris Rarden says:

    How would I modify this script to submit a status update to my own twitter account ?

  15. 23rd Apr

    benoit says:

    Thanks a lot for this tutorial : it works great for GET requests without any parameters but as soon as I add one, I get an error

    Let’s say the URL is

    1
    $url = "http://api.twitter.com/1/statuses/home_timeline.json?count=5";

    I get

    1
    2
    3
    4
    {
    error: "Could not authenticate with OAuth.",
    request: "/1/statuses/home_timeline.json?count=5"
    }

    whereas it works fine when I just use

    1
    $url = "http://api.twitter.com/1/statuses/home_timeline.json?count=5";

    How do you add GET parameters without messing up the authentication ?

  16. Twitter API Made Easy | Blogrescue.com

    10th May

    Twitter API Made Easy | Blogrescue.com pinged back:

    [...] on NestWork, I needed to send Twitter API requests that were authenticated for different users. This excellent post got me about 95% of the way there. The two missing pieces [...]

Add your thoughts

  • XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>