Twitter API: PIN-based OAuth Using PHP

A few weeks ago we discussed Automated Serverside Tweeting Using OAuth (read this before going on) and I kept looking deeper into security issues, so I found a way to make things slightly simpler. If you played with the OAuth Clients page on Twitter, you know that there are two ways of authentication – web application and client application. Also, I found out that there’s a redirect_to parameter in OAuth authentication, although we’re not going to use the original web redirects this time. If we’re talking about automatic server-side tweeting, then it should be serverside, right? So why not close down HTTP access at all?

The downside of all this is that you’re unable to have two applications (web and client) with the same name, thus you cannot create a web application and a client application that would return the same “from” string in tweets, so you should probably divide your app in two parts, say “AppName” (web application) and “AppName Server” (client application) and feel free to link them to the same URL.

Pin based Twitter OAuth works just like the original (web) OAuth (request tokens, access tokens) but instead of returning back to a web page, Twitter gives out a Pin code that you have to input into your app in order to exchange its request token with an access token. It’s fairly simple, but unfortunatelly Abraham Williams didn’t implement this part into his Twitter OAuth php library, but we’re still going to use it, with some slight modifications.

Assuming we’ve initiated an OAuth session and stored the request tokens, here’s the original piece of code that exchanges the request tokens with the access tokens (the ones that actually give you the right to call the Twitter API via OAuth):

$oauth = new TwitterOAuth($consumer_key, $consumer_secret,
$request_token, $request_token_secret);

// Ask Twitter for an access token (and an access token secret)
$request = $oauth->getAccessToken();

$access_token = $request['oauth_token'];
$access_token_secret = $request['oauth_token_secret'];

The getAccessToken function is the one that posts the request to exchange request tokens for access tokens. It’s the one we have to modify to implement the pin code solution, so open up twitterOAuth.php, find the function (it’s around line 100) and make it look like this:

function getAccessToken($token = NULL, $pin = NULL)
{
	if ($pin)
		$r = $this->oAuthRequest($this->accessTokenURL(),
			array("oauth_verifier" => $pin));
	else
		$r = $this->oAuthRequest($this->accessTokenURL());

	$token = $this->oAuthParseResponse($r);
	$this->token = new OAuthConsumer($token['oauth_token'],
		$token['oauth_token_secret']);

	return $token;
}

What we did is add an extra parameter right after $token which is optional (not to break all the other code) – $pin. Now in terms of OAuth, the pin code is called the OAuth verifier (oauth_verifier), we add it as a parameter to the oAuthRequest call, which then wraps it up into a signed HTTP request to Twitter containing the verifier (line 114).

Back to our script. The rest is simple, just change the getAccessToken call to look like this:

$request = $oauth->getAccessToken(NULL, $pin);

Where $pin would be the pin code provided by Twitter during OAuth. Now, move all your scripts into a secured place, preferably not accessible through HTTP, write a few modifications in order to pass parameters through command line (use $argv[n] instead of $_GET[…]). Here’s a tip on how it should look to get you on the right track. All the work is done through SSH:

# php oauth.php register
Request tokens aquired, proceed to this link: https://twitter.com/oauth/authorize?oauth_token=whatever

# php oauth.php validate 123456
Access tokens stored, identified as @twittername

# php oauth.php reset
Access tokens deleted

That’s the way my script works and voila! No more HTTP! Hmm.. TwiBots? ;)

About the author

Konstantin Kovshenin

WordPress Core Contributor, ex-Automattician, public speaker and consultant, enjoying life in Moscow. I blog about tech, WordPress and DevOps.

5 comments

  • Konstantin,
    Your two posts on accessing Twitter's OAuth were extremely helpful in getting my own Twitterbot (@franklinyopo) ready for the transition from basic authentication to OAuth. However, some things have changed in Abraham's library since the time of these posts, and I'd like to mention my own mistakes in using your process.

    First, you need to mention that you need to be sure your callback url is set to 'oob' when using PIN-based authentication. Abraham's library has a config.php that sets the CALLBACK_URL, CONSUMER_KEY, and CONSUMER_KEY_SECRET constants, and this was tripping me up when I copied your code.

    In your previous post's code segments you make calls to the OAuthRequest method with parameter order (URL, param array(), HTTP METHOD). As of the 0.2.0-beta3 version of the php oauth library, the method order is (URL, METHOD, param array()). For example,

    $oauth->OAuthRequest('https://twitter.com/statuses/update.xml','POST',array('status' => "Hey! I'm posting via #OAuth!") );

    Finally, I have a few questions. What does your script do when you send the 'reset' argument in the command line? Does it just delete the files that contain your access tokens?

    How do you retrieve the PIN on the command line after registering the session? I am using fopen and parsing out the PIN, but do you have a more elegant solution?

    Thanks again for your post, and I'll be writing up my own experiences pretty soon. I'll post the link to it once I'm finished.

    John

  • Before anyone tries this, Abraham has fixed this in the latest version available on his GitHub. Call getAccessToken with the PIN as the only variable, like so: $oauth->getAccessToken($pin)

    And it will do out-of-band auth ;)