WordPress
Article

OAuth, Twitter, the WordPress HTTP API and You

By Collins Agbonghama

In previous tutorials, we took a deep dive into the WordPress HTTP API. We even went as far as building the following plugins to demonstrate real-world examples of its usage: domain whois and social data widget; CAPTCHA protection plugin for WordPress login, registration & comment; and plugin for stopping disposable email address signup.

In this tutorial, we’ll be introduced to the world of OAuth, how Twitter uses it for authorizing HTTP requests to its API and finally, building a PHP class powered by WordPress HTTP API that plugins can take advantage of when consuming Twitter.

Introduction to OAuth

OAuth is an authentication protocol that provides a simple, safer and more secure way to publish and interact with protected data. It allows users to approve applications to act on their behalf without sharing their password.

If you’re storing protected data on your users’ behalf, they shouldn’t be spreading their passwords around the web to get access to it. Instead, you can use OAuth to give your users access to their data, while protecting their account credentials.

Coding the PHP Class

A run-down on how HTTP requests to Twitter are made with OAuth authentication will be explained as we code the PHP class.

First off, head over to Twitter’s Application management center; create an application to grab your keys and access token.

A step-by-step guide on creating Twitter applications and getting the API keys can be found at hostoople.com

Create the PHP class and include the properties that will store the various parameters. These are outlined below.

class Twitter_API_WordPress {

	/** @var string OAuth access token */
	private $oauth_access_token;

	/** @var string OAuth access token secrete */
	private $oauth_access_token_secret;

	/** @var string Consumer key */
	private $consumer_key;

	/** @var string consumer secret */
	private $consumer_secret;

	/** @var array POST parameters */
	private $post_fields;

	/** @var string GET parameters */
	private $get_field;

	/** @var array OAuth credentials */
	private $oauth_details;

	/** @var string Twitter's request URL */
	private $request_url;

	/** @var string Request method or HTTP verb */
	private $request_method;

The constructor will accept an array of your Twitter’s application consumer (or API) key and secret, as well as access token and access token secret and save them to their respective properties.

/** Class constructor */
	public function __construct( $settings ) {

		if ( ! isset( $settings['oauth_access_token'] )
		     || ! isset( $settings['oauth_access_token_secret'] )
		     || ! isset( $settings['consumer_key'] )
		     || ! isset( $settings['consumer_secret'] )
		) {
			return new WP_Error( 'twitter_param_incomplete', 'Make sure you are passing in the correct parameters' );
		}

		$this->oauth_access_token        = $settings['oauth_access_token'];
		$this->oauth_access_token_secret = $settings['oauth_access_token_secret'];
		$this->consumer_key              = $settings['consumer_key'];
		$this->consumer_secret           = $settings['consumer_secret'];
	}

Next are the methods that will accept the GET or POST parameters for the HTTP request.

/**
	 * Store the POST parameters
	 *
	 * @param array $array array of POST parameters
	 *
	 * @return $this
	 */
	public function set_post_fields( array $array ) {
		$this->post_fields = $array;

		return $this;
	}


	/**
	 * Store the GET parameters
	 *
	 * @param $string
	 *
	 * @return $this
	 */
	public function set_get_field( $string ) {
		$this->getfield = $string;

		return $this;
	}

The private method _build_signature_base_string() accepts the following arguments to create the signature base string: the request URL, the request method or HTTP verb and the OAuth credentials (consumer key and secret; access token and secret; and the GET parameters if it is a GET request).

/**
	 * Create a signature base string from list of arguments
	 *
	 * @param string $request_url request url or endpoint
	 * @param string $method HTTP verb
	 * @param array $oauth_params Twitter's OAuth parameters
	 *
	 * @return string
	 */
	private function _build_signature_base_string( $request_url, $method, $oauth_params ) {
		// save the parameters as key value pair bounded together with '&'
		$string_params = array();

		ksort( $oauth_params );

		foreach ( $oauth_params as $key => $value ) {
			// convert oauth parameters to key-value pair
			$string_params[] = "$key=$value";
		}

		return "$method&" . rawurlencode( $request_url ) . '&' . rawurlencode( implode( '&', $string_params ) );
	}

The _generate_oauth_signature() private method accepts the created signature base string to generate the OAuth signature.

private function _generate_oauth_signature( $data ) {

	// encode consumer and token secret keys and subsequently combine them using & to a query component
	$hash_hmac_key = rawurlencode( $this->consumer_secret ) . '&' . rawurlencode( $this->oauth_access_token_secret );

	$oauth_signature = base64_encode( hash_hmac( 'sha1', $data, $hash_hmac_key, true ) );

	return $oauth_signature;
}

The build_oauth() creates an array containing the following data and saves it to the oauth_details property, which will be use later by authorization_header() to generate the authorization header.

  • oauth_consumer_key – Twitter application consumer key.
  • oauth_nonce – a random string, uniquely generated by the client to allow the server to verify that a request has never been made before often created using time() or mt_rand().
  • oauth_signature_method – the signature method which is often times “HMAC-SHA1”
  • oauth_token – application OAuth token.
  • oauth_timestamp – current timestamp created with time()
  • oauth_version – Twitter uses version 1.0
  • oauth_signature – OAuth signature generated by _generate_oauth_signature()

The request method or HTTP verb is also saved to request_method property.

/**
	 * Build, generate and include the OAuth signature to the OAuth credentials
	 *
	 * @param string $request_url Twitter endpoint to send the request to
	 * @param string $request_method Request HTTP verb eg GET or POST
	 *
	 * @return $this
	 */
	public function build_oauth( $request_url, $request_method ) {
		if ( ! in_array( strtolower( $request_method ), array( 'post', 'get' ) ) ) {
			return new WP_Error( 'invalid_request', 'Request method must be either POST or GET' );
		}

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

		if ( ! is_null( $this->get_field ) ) {
			// remove question mark(?) from the query string
			$get_fields = str_replace( '?', '', explode( '&', $this->get_field ) );

			foreach ( $get_fields as $field ) {
				// split and add the GET key-value pair to the post array.
				// GET query are always added to the signature base string
				$split                          = explode( '=', $field );
				$oauth_credentials[ $split[0] ] = $split[1];
			}
		}

		// convert the oauth credentials (including the GET QUERY if it is used) array to query string.
		$signature = $this->_build_signature_base_string( $request_url, $request_method, $oauth_credentials );

		$oauth_credentials['oauth_signature'] = $this->_generate_oauth_signature( $signature );

		// save the request url for use by WordPress HTTP API
		$this->request_url = $request_url;

		// save the OAuth Details
		$this->oauth_details = $oauth_credentials;

		$this->request_method = $request_method;

		return $this;
	}

Here is the code for the authorization_header() method we talked about.

/**
	 * Generate the authorization HTTP header
	 * @return string
	 */
	public function authorization_header() {
		$header = 'OAuth ';

		$oauth_params = array();
		foreach ( $this->oauth_details as $key => $value ) {
			$oauth_params[] = "$key=\"" . rawurlencode( $value ) . '"';
		}

		$header .= implode( ', ', $oauth_params );

		return $header;
	}

The process_request() will send the GET or POST request using wp_remote_get() or wp_remote_post() depending on the request method and subsequently return the response using wp_remote_retrieve_body().

/**
	 * Process and return the JSON result.
	 *
	 * @return string
	 */
	public function process_request() {

		$header = $this->authorization_header();

		$args = array(
			'headers'   => array( 'Authorization' => $header ),
			'timeout'   => 45,
			'sslverify' => false
		);

		if ( ! is_null( $this->post_fields ) ) {
			$args['body'] = $this->post_fields;

			$response = wp_remote_post( $this->request_url, $args );

			return wp_remote_retrieve_body( $response );
		}

		else {

			// add the GET parameter to the Twitter request url or endpoint
			$url = $this->request_url . $this->get_field;

			$response = wp_remote_get( $url, $args );

			return wp_remote_retrieve_body( $response );

		}

	}

See this tutorial for a better understanding of the WordPress HTTP API and how it works.

And finally, we close the class.

} // Twitter_API_WordPress

Please note: In set_post_fields(), set_get_field() and build_oauth(), the object $this is returned in each method in order to support method chaining.

Example:

$SomeObject->getObjectOne()->getObjectTwo()

See the class usage below for a better understanding.

How to Use the Class

This class must be used within the context of a WordPress plugin. It won’t work as a standalone class because it requires the WordPress HTTP API for it to work.

To get a list or collection of your most recent tweets, follow the guide below.
Note: https://api.twitter.com/1.1/statuses/user_timeline.json is the resource URL for retrieving the recent tweet data.

First, create an array of your access keys and tokens.

$settings = array(
	'oauth_access_token' => "211978035-tcdnwn5GlzeY9tKiMqTvkSLNPAgcwO5ABtqwgx18",
	'oauth_access_token_secret' => "rS0CMxoVNmcUYG5nWi2OhY8bJdFnK3p4W99KSyJ5BU7Iv",
	'consumer_key' => "qFt8kyGlietTJoduRItBAU2oJ",
	'consumer_secret' => "YWlaR5amBQWlwB62Uah8hjNoCnYYme7tMcrUDg0Z9SKaFvh4eC"
);

Set the request URL and Method where w3guy is your Twitter username.

$url            = 'https://api.twitter.com/1.1/statuses/user_timeline.json';
$getfield       = '?screen_name=w3guy';
$request_method = 'GET';

Finally, process the request like so.

$twitter_instance = new Twitter_API_WordPress( $settings );

$result = $twitter_instance
	->set_get_field( $getfield )
	->build_oauth( $url, $request_method )
	->process_request();

If all goes well, the variable $result will be populated with a JSON data of your recent tweets.

For a POST request, for example, say you want to update your profile description.

$settings = array(
	'oauth_access_token'        => "211978035-tcdnwn5GlzeY9tKiMqTvkSLNPAgcwO5ABtqwgx18",
	'oauth_access_token_secret' => "rS0CMxoVNmcUYG5nWi2OhY8bJdFnK3p4W99KSyJ5BU7Iv",
	'consumer_key'              => "qFt8kyGlietTJoduRItBAU2oJ",
	'consumer_secret'           => "YWlaR5amBQWlwB62Uah8hjNoCnYYme7tMcrUDg0Z9SKaFvh4eC"
);

/** POST fields required by the URL above. See relevant docs as above **/
$url = 'https://api.twitter.com/1.1/account/update_profile.json';

$postField = array(
	'description' => 'Web Developer, Writer, Geek'
);

$request_method = 'POST';

$instance = new Twitter_API_WordPress( $settings );


$update = $instance
	->set_post_fields( $postField )
	->build_oauth( $url, $request_method )
	->process_request();

Credit & Resources

The structure and code of this class was inspired by James Mallison’s PHP Twitter client.

To learn more about Twitter API and OAuth, see the resources below.

Conclusion

In this article, we learned about OAuth and how to consume Twitter using an HTTP client class powered by WordPress HTTP API. As previously stated, this class should be used within a WordPress plugin because it uses the WordPress HTTP API, which is only present or instantiated when WordPress is loaded. This PHP class can come in handy in building, for example, a recent tweets widget.

The code is available on GitHub. Feel free to fork and even submit pull requests.

Be sure to subscribe to the WordPress channel to keep abreast of my upcoming tutorials.

Happy Coding.

Comments
KirkPettinga

Thanks for the post! It was extremely helpful in getting my list feed set up. A small typo I noticed though is in the "set_get_field" function. I was getting an error that I wasn't providing an owner_id/slug combo, even though I was. So I did some digging and here's what I fixed:

$this->getfield = $string;

should actually be

$this->get_field = $string;

Once I inserted that underscore it worked perfectly. Again, thanks for the post!

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in WordPress, once a week, for free.