Table of Contents

1.0 Introduction
2.0 Deriving Authorization HTTP Request Header Value
2.1 … Twitter generated OAuth params
2.2 … oauth_signature
2.3 … Building the OAuth Header Value
3.0 Invoking the Twitter API using cURL
4.0 Summary
5.0 Appendix
5.1 … Reference
5.2 … The Twitter Class

1.0 Introduction

Recently Twitter retired 1.0 APIs. With 1.1 APIs, Twitter mandates authentication. True, OAuth 1.0a based authentication. So gone are the days when we were able to access Twitter feeds using 1.0 APIs without authentication. No worries though. Twitter expects a valid value for HTTP header Authorization similar to the one shown below.

> GET /1.1/statuses/user_timeline.json?screen_name=sangeethlabs&trim_user=1&include_entities=&exclude_replies=1&include_rts=&count=1 HTTP/1.1
> Host: api.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="sdfERdf3434sdWEddf23d", oauth_nonce="1373207246", oauth_signature_method="HMAC-SHA1", oauth_token="8749687284-XrindkI9QRm3ab8MWcQg4kXCYTz1NOS8yF1E2FFGN", oauth_timestamp="1373207246", oauth_version="1.0", oauth_signature="%2FpEI6thDB7zCYjkS93Jb8D%2FuQWjS%3D"

In order to derive the Authorization header value, we need values for the following components.

  1. oauth_consumer_key
  2. oauth_nonce
  3. oauth_token
  4. oauth_timestamp
  5. oauth_signature

The following sections explain how the above components are derived, how it can be implemented using PHP and finally shows a simple example to fetch the latest tweet using /statuses/user_timeline API.

2.0 Deriving Authorization HTTP Request Header Value

2.1 Twitter generated OAuth params

The values for oauth_consumer_key and oauth_token need to be created from Twitter website by following the steps mentioned below

  1. Sign Up for Twitter in case you do not have one.
  2. Create a new Application using Twitter and get the consumer_key and consumer_secret.
  3. Create your OAuth access token and secret (i.e oauth_access_token and oauth_access_token_secret).
    NOTE: Once you create an Application, the same page guides you to generate the OAuth access token.

So at this stage the OAuth parameters for which we have the values are

OAuth Param Value
oauth_consumer_key consumer_key
oauth_token oauth_access_token

The values of consumer_secret and oauth_access_token_secret are required for creating oauth_signature.

2.2 oauth_signature

In order to create the value for oauth_signature, I would recommend you to read the article named Creating a signature at Twitter developers website. In order to help PHP developers, I have translated the steps into PHP.

Step 1: Collecting the request method and URL

Since our objective is to fetch the latest tweets,

Request method GET
Base URL https://api.twitter.com/1.1/statuses/user_timeline.json

Step 2: Collecting parameters

In order to get the latest tweets from @sangeethlabs, the list of Request-parameters required are

Request Param Value
screen_name sangeethlabs
trim_user true
include_entities false
exclude_replies true
include_rts false
count 1

NOTE: In order to know the meaning of each of the above request parameters, please read the manual of /statuses/user_timeline API.

Further, All OAuth-parameters other than oauth_signature are also considered as parameters. So we have

OAuth Param Value
oauth_consumer_key consumer_key
oauth_nonce (The current time)
oauth_signature_method HMAC-SHA1
oauth_token oauth_access_token
oauth_timestamp (The current time)
oauth_version 1.0

The following code helps to create the Parameter string.

<?php
$v = array();
$all_params = array_merge($oauthParams, $requestParams);
ksort($all_params);

foreach($all_params as $key=>$value) {
    $v[] = "$key=" . rawurlencode($value);
}

$parameterString = rawurlencode(implode('&', $v));
?>

Step 3: Creating the signature base string

The following code helps to create the Signature base string which then used to create the signature.

<?php
$signatureBaseString = $httpMethod 
                       . '&' 
                       . rawurlencode($baseURI) 
                       . '&' 
                       . $parameterString;
?>

Step 4: Getting a signing key

The following code show how to create a Signing key

<?php
$signing_key = rawurlencode($consumer_secret) 
               . '&' 
               . rawurlencode($oauth_access_token_secret);
?>

Step 5: Calculating the signature

<?php
$oauth_signature = base64_encode(hash_hmac('sha1', $signature_base_string, $signing_key, true));
?>

2.3 Building the OAuth Header Value

<?php 
$values = array();
foreach($oauthParams as $key=>$value) {
    $values[] = "$key=\"" . rawurlencode($value) . "\"";
}     
$headerValue = 'OAuth ' . implode(', ', $values);
?>

Finally, we have the value for HTTP header Authorization . The following sections will show how to use the OAuth header value and invoke /statuses/user_timeline API.

3.0 Invoking the Twitter API using cURL

In order to invoke the Twitter API as mentioned above we need the following parameters

  1. url
  2. request params
  3. authorization header value

In the previous sections we have computed the values for these three parameters. With these parameters, we can use the following code to invoke the Twitter API using cURL.

<?php
// Invoke the Twitter API using cURL functions           
$ch = curl_init();

// Create the API URI appended with the query parameters
$url = $this->buildURL($url, $requestParams);
$values = array();
foreach($queryParams as $key=>$value) {
    $values[] = "$key=" . rawurlencode($value);
}
$queryString = implode('&', $values);
return "$url?$queryString";      


curl_setopt_array($ch,
                  array( 
                        CURLOPT_URL => $url,
                        CURLOPT_HTTPHEADER => array("Authorization: $authorization_header_value"),
                        CURLOPT_HEADER => false,
                        CURLOPT_RETURNTRANSFER => true,
                        CURLOPT_SSL_VERIFYPEER => false
                  ));
$twitter_response = curl_exec($ch);

if (empty($twitter_response)) {
	$errorMessage = curl_error($ch);
	curl_close($ch);
    throw new Exception($errorMessage);
}

$info = curl_getinfo($ch);
    
curl_close($ch);

$json = json_decode($twitter_response, true);
        
$responseCode = $info['http_code'];
if ($responseCode != '200') {
    throw new Exception($json['errors'][0]['message'], 
                        $json['errors'][0]['code']);
}
?>

4.0 Summary

Now using our new Twitter class and with the values of oauth_access_token, oauth_access_token_secret, consumer_key and consumer_secret, we can invoke /statuses/user_timeline API to get the latest tweet from @sangeethlabs as shown below

<?php
$oauth_access_token = "...YOUR OAUTH ACCESS TOKEN...";
$oauth_access_token_secret = "...YOUR OAUTH ACCESS TOKEN SECRET...";
$consumer_key = "...YOUR CONSUMER KEY...";
$consumer_secret = "...YOUR CONSUMER SECRET...";

$twitter = new Twitter($oauth_access_token, 
                 $oauth_access_token_secret,
                 $consumer_key,
                 $consumer_secret);
//$twitter->setVerboseEnabled(true);

try {                 
   $json = $twitter->get("/statuses/user_timeline.json", 
                         array(
                            'screen_name'=>'sangeethlabs',
                            'trim_user'=> true,
                            'include_entities'=> false,
                            'exclude_replies'=> true,
                            'include_rts' => true,
                            'count' => 1
                         ));
   echo "Last Tweet\n"
        . "Time: " . $json[0]['created_at'] . "\n"
        . "Text: " . $json[0]['text'] . "\n\n";
} catch (Exception $e) {
   echo "Error: {$e->getCode()} - {$e->getMessage()}\n";
}
?>

5.0 Appendix

5.1 Reference

  1. stackoverflow.com – Simplest PHP example for retrieving user_timeline with Twitter API version 1.1
  2. twitter.com – GET statuses/user_timeline
  3. twitter.com – Creating a signature
  4. twitter.com – Authorizing a request
  5. ietf.org – The OAuth 1.0 protocol
  6. php.net – cURL Functions

5.2 The Twitter Class

  1 <?php
  2 class Twitter {
  3    private $oauth_access_token = "";
  4    private $oauth_access_token_secret = "";
  5    private $consumer_key = "";
  6    private $consumer_secret = "";
  7    private $verboseEnabled = false;
  8 
  9    function __construct($oauth_access_token, 
 10                         $oauth_access_token_secret,
 11                         $consumer_key,
 12                         $consumer_secret) {
 13         $this->oauth_access_token = $oauth_access_token; 
 14         $this->oauth_access_token_secret = $oauth_access_token_secret;
 15         $this->consumer_key = $consumer_key;
 16         $this->consumer_secret = $consumer_secret;
 17    }
 18    
 19    private function buildSignatureBaseString($httpMethod, $baseURI, $requestParams, $oauthParams) {
 20         // Collecting parameters an building the 'Parameter string'
 21         $v = array();
 22         $all_params = array_merge($oauthParams, $requestParams);
 23         ksort($all_params);
 24         
 25         foreach($all_params as $key=>$value) {
 26            $v[] = "$key=" . rawurlencode($value);
 27         }
 28         $parameterString = rawurlencode(implode('&', $v));
 29         
 30         // Building the 'Signature base string'
 31         return $httpMethod 
 32                . '&' 
 33                . rawurlencode($baseURI) 
 34                . '&' 
 35                . $parameterString;
 36    }
 37 
 38    private function buildAuthorizationHeaderValue($oauthParams) {
 39         $r = 'OAuth ';
 40         $values = array();
 41         foreach($oauthParams as $key=>$value) {
 42             $values[] = "$key=\"" . rawurlencode($value) . "\"";
 43         }     
 44         $r .= implode(', ', $values);
 45         return $r;
 46    }
 47    
 48    private function buildOuthSignature($signature_base_string) {
 49         $signing_key = rawurlencode($this->consumer_secret) 
 50                        . '&' 
 51                        . rawurlencode($this->oauth_access_token_secret);
 52                        
 53         $oauth_signature = base64_encode(hash_hmac('sha1', $signature_base_string, $signing_key, true));
 54         
 55         return $oauth_signature;
 56    }
 57    
 58    private function buildURL($url, $queryParams) {
 59         $values = array();
 60         foreach($queryParams as $key=>$value) {
 61             $values[] = "$key=" . rawurlencode($value);
 62         }
 63         $queryString = implode('&', $values);
 64         return "$url?$queryString";      
 65    }
 66    
 67    public function setVerboseEnabled($verboseEnabled) {
 68         $this->verboseEnabled = $verboseEnabled;
 69    }
 70    
 71    public function get($api, $requestParams) { 
 72         $url = "https://api.twitter.com/1.1". $api;
 73     
 74         $oauthParams = array( 'oauth_consumer_key' => $this->consumer_key,
 75                         'oauth_nonce' => time(),
 76                         'oauth_signature_method' => 'HMAC-SHA1',
 77                         'oauth_token' => $this->oauth_access_token,
 78                         'oauth_timestamp' => time(),
 79                         'oauth_version' => '1.0');
 80 
 81         $signature_base_string = $this->buildSignatureBaseString('GET', $url, $requestParams, $oauthParams);
 82         if ($this->verboseEnabled) {        
 83             echo "Signature base string:\n$signature_base_string\n\n";
 84         }
 85         
 86         $oauth_signature = $this->buildOuthSignature($signature_base_string);
 87         if ($this->verboseEnabled) {        
 88             echo "OAuth signature:\n$oauth_signature\n\n";
 89         }
 90         $oauthParams['oauth_signature'] = $oauth_signature;
 91                 
 92         $authorization_header_value = $this->buildAuthorizationHeaderValue($oauthParams);
 93         if ($this->verboseEnabled) {
 94             echo "Authorization header:\nAuthorization: $authorization_header_value\n\n";
 95         }
 96                    
 97         // Invoke the Twitter API using cURL functions           
 98         $ch = curl_init();
 99         
100         // Create the API URI appended with the query parameters
101         $url = $this->buildURL($url, $requestParams);
102         if ($this->verboseEnabled) {        
103             echo "Request URL:\n$url\n\n";
104         }
105         curl_setopt_array($ch,
106                           array( 
107                                 CURLOPT_URL => $url,
108                                 CURLOPT_HTTPHEADER => array("Authorization: $authorization_header_value"),
109                                 CURLOPT_HEADER => false,
110                                 CURLOPT_RETURNTRANSFER => true,
111                                 CURLOPT_SSL_VERIFYPEER => false
112                           ));
113         if ($this->verboseEnabled) {
114             curl_setopt($ch, CURLOPT_VERBOSE, TRUE); 
115         }
116         $twitter_response = curl_exec($ch);
117         
118         if (empty($twitter_response)) {
119 			$errorMessage = curl_error($ch);
120 			curl_close($ch);
121 		    throw new Exception($errorMessage);
122         }
123         
124         $info = curl_getinfo($ch);
125             
126         curl_close($ch);
127         
128         if ($this->verboseEnabled) {
129             echo "Response Body:\n$twitter_response\n\n";
130         }
131 
132         $json = json_decode($twitter_response, true);
133                 
134         $responseCode = $info['http_code'];
135         if ($responseCode != '200') {
136             throw new Exception($json['errors'][0]['message'], 
137                                 $json['errors'][0]['code']);
138         }
139         
140         unset( $requestParams );
141         unset( $oauthParams );
142         
143         return $json;
144     }
145 }
146 ?>