8000 OAuth2 app-only auth · codezninja/codebird-php@d277713 · GitHub
[go: up one dir, main page]

Skip to content

Commit d277713

Browse files
committed
OAuth2 app-only auth
1 parent b465c0f commit d277713

File tree

1 file changed

+125
-33
lines changed

1 file changed

+125
-33
lines changed

codebird.php

Lines changed: 125 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<?php
22

33
/**
4-
* A simple wrapper for the Twitter API
4+
* A Twitter library in PHP.
55
*
66
* @package codebird
7+
* @version 2.3.0
78
* @author J.M. <me@mynetx.net>
8-
* @copyright 2010-2012 J.M. <me@mynetx.net>
9+
* @copyright 2010-2013 J.M. <me@mynetx.net>
910
*
1011
* This program is free software: you can redistribute it and/or modify
1112
* it under the terms of the GNU General Public License as published by
@@ -33,7 +34,7 @@
3334
unset($id);
3435

3536
/**
36-
* A simple wrapper for the Twitter API
37+
* A Twitter library in PHP.
3738
*
3839
* @package codebird
3940
* @subpackage codebird-php
@@ -55,20 +56,25 @@ class Codebird
5556
*/
5657
private static $_oauth_consumer_secret = null;
5758

59+
/**
60+
* The app-only bearer token. Used to authorize app-only requests
61+
*/
62+
private static $_oauth_bearer_token = null;
63+
5864
/**
5965
* The API endpoint to use
6066
*/
61-
private $_endpoint = 'https://api.twitter.com/1.1/';
67+
private static $_endpoint = 'https://api.twitter.com/1.1/';
6268

6369
/**
6470
* The API endpoint to use for OAuth requests
6571
*/
66-
private $_endpoint_oauth = 'https://api.twitter.com/';
72+
private static $_endpoint_oauth = 'https://api.twitter.com/';
6773

6874
/**
6975
* The API endpoint to use for untransitioned methods
7076
*/
71-
private $_endpoint_old = 'https://api.twitter.com/1/';
77+
private static $_endpoint_old = 'https://api.twitter.com/1/';
7278

7379
/**
7480
* The Request or access token. Used to sign requests
@@ -98,7 +104,7 @@ class Codebird
98104
/**
99105
* The current Codebird version
100106
*/
101-
private $_version = '2.2.3';
107+
private $_version = '2.3.0';
102108

103109
/**
104110
* Returns singleton class instance
@@ -128,6 +134,18 @@ public static function setConsumerKey($key, $secret)
128134
self::$_oauth_consumer_secret = $secret;
129135
}
130136

137+
/**
138+
* Sets the OAuth2 app-only auth bearer token
139+
*
140+
* @param string $token OAuth2 bearer token
141+
*
142+
* @return void
143+
*/
144+
public static function setBearerToken($token)
145+
{
146+
self::$_oauth_bearer_token = $token;
147+
}
148+
131149
/**
132150
* Gets the current Codebird version
133151
*
@@ -186,6 +204,10 @@ public function __call($fn, $params)
186204
parse_str($params[0], $apiparams);
187205
}
188206
}
207+
$app_only_auth = false;
208+
if (count($params) > 1) {
209+
$app_only_auth = !! $params[1];
210+
}
189211

190212
// map function name to API method
191213
$method = '';
@@ -239,7 +261,14 @@ public function __call($fn, $params)
239261
// geek-geek: Now allowing to specify filenames as params
240262
$this->_detectFilenames($method_template, $apiparams);
241263

242-
return $this->_callApi($httpmethod, $method, $method_template, $apiparams, $multipart);
264+
return $this->_callApi(
265+
$httpmethod,
266+
$method,
267+
$method_template,
268+
$apiparams,
269+
$multipart,
270+
$app_only_auth
271+
);
243272
}
244273

245274
/**
@@ -279,7 +308,7 @@ public function oauth_authenticate()
279308
if ($this->_oauth_token == null) {
280309
throw new Exception('To get the authenticate URL, the OAuth token must be set.');
281310
}
282-
return $this->_endpoint_oauth . 'oauth/authenticate?oauth_token=' . $this->_url($this->_oauth_token);
311+
return self::$_endpoint_oauth . 'oauth/authenticate?oauth_token=' . $this->_url($this->_oauth_token);
283312
}
284313

285314
/**
@@ -292,7 +321,55 @@ public function oauth_authorize()
292321
if ($this->_oauth_token == null) {
293322
throw new Exception('To get the authorize URL, the OAuth token must be set.');
294323
}
295-
return $this->_endpoint_oauth . 'oauth/authorize?oauth_token=' . $this->_url($this->_oauth_token);
324+
return self::$_endpoint_oauth . 'oauth/authorize?oauth_token=' . $this->_url($this->_oauth_token);
325+
}
326+
327+
/**
328+
* Gets the OAuth bearer token
329+
*
330+
* @return string The OAuth bearer token
331+
*/
332+
333+
public function oauth2_token()
334+
{
335+
if (! function_exists('curl_init')) {
336+
throw new Exception('To make API requests, the PHP curl extension must be available.');
337+
}
338+
if (self::$_oauth_consumer_key == null) {
339+
throw new Exception('To obtain a bearer token, the consumer key must be set.');
340+
}
341+
$ch = false;
342+
$post_fields = array(
343+
'grant_type' => 'client_credentials'
344+
);
345+
$url = self::$_endpoint_oauth . 'oauth2/token';
346+
$ch = curl_init($url);
347+
curl_setopt($ch, CURLOPT_POST, 1);
348+
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
349+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
350+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
351+
curl_setopt($ch, CURLOPT_HEADER, 1);
352+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
353+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
354+
curl_setopt($ch, CURLOPT_USERPWD, self::$_oauth_consumer_key . ':' . self::$_oauth_consumer_secret);
355+
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
356+
'Expect:'
357+
));
358+
$reply = curl_exec($ch);
359+
$httpstatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
360+
$reply = $this->_parseApiReply('oauth2/token', $reply);
361+
if ($this->_return_format == CODEBIRD_RETURNFORMAT_OBJECT) {
362+
$reply->httpstatus = $httpstatus;
363+
if ($httpstatus == 200) {
364+
self::setBearerToken($reply->access_token);
365+
}
366+
} else {
367+
$reply['httpstatus'] = $httpstatus;
368+
if ($httpstatus == 200) {
369+
self::setBearerToken($reply['access_token']);
370+
}
371+
}
372+
return $reply;
296373
}
297374

298375
/**
@@ -374,12 +451,10 @@ private function _nonce($length = 8)
374451
* @param string $httpmethod Usually either 'GET' or 'POST' or 'DELETE'
375452
* @param string $method The API method to call
376453
* @param array optional $params The API call parameters, associative
377-
* @param bool optional $multipart Whether the request is going to be multipart/form-data
378454
*
379-
* @return string The API call parameters including the signature
380-
* If multipart, the Authorization HTTP header is returned
455+
* @return string Authorization HTTP header
381456
*/
382-
private function _sign($httpmethod, $method, $params = array(), $multipart = false)
457+
private function _sign($httpmethod, $method, $params = array())
383458
{
384459
if (self::$_oauth_consumer_key == null) {
385460
throw new Exception('To generate a signature, the consumer key must be set.');
@@ -398,6 +473,7 @@ private function _sign($httpmethod, $method, $params = array(), $multipart = fal
398473
if ($this->_oauth_token != null) {
399474
$sign_base_params['oauth_token'] = $this->_url($this->_oauth_token);
400475
}
476+
$oauth_params = $sign_base_params;
401477
foreach ($params as $key => $value) {
402478
$sign_base_params[$key] = $this->_url($value);
403479
}
@@ -408,18 +484,16 @@ private function _sign($httpmethod, $method, $params = array(), $multipart = fal
408484
}
409485
$sign_base_string = substr($sign_base_string, 0, -1);
410486
$signature = $this->_sha1($httpmethod . '&' . $this->_url($method) . '&' . $this->_url($sign_base_string));
411-
if ($multipart) {
412-
$params = array_merge($sign_base_params, array(
413-
'oauth_signature' => $signature
414-
));
415-
ksort($params);
416-
$authorization = 'Authorization: OAuth ';
417-
foreach ($params as $key => $value) {
418-
$authorization .= $key . '="' . $this->_url($value) . '", ';
419-
}
420-
return substr($authorization, 0, -2);
487+
488+
$params = array_merge($oauth_params, array(
489+
'oauth_signature' => $signature
490+
));
491+
ksort($params);
492+
$authorization = 'Authorization: OAuth ';
493+
foreach ($params as $key => $value) {
494+
$authorization .= $key . '="' . $this->_url($value) . '", ';
421495
}
422-
return ($httpmethod == 'GET' ? $method . '?' : '') . $sign_base_string . '&oauth_signature=' . $this->_url($signature);
496+
return substr($authorization, 0, -2);
423497
}
424498

425499
/**
@@ -585,7 +659,9 @@ private function _detectMethod($method, $params)
585659

586660
// OAuth
587661
'oauth/access_token',
588-
'oauth/request_token'
662+
'oauth/request_token',
663+
'oauth2/token',
664+
'oauth2/invalidate_token'
589665
);
590666
foreach ($httpmethods as $httpmethod => $methods) {
591667
if (in_array($method, $methods)) {
@@ -710,12 +786,12 @@ private function _detectFilenames($method, &$params)
710786
*/
711787
private function _getEndpoint($method, $method_template)
712788
{
713-
if (substr($method, 0, 6) == 'oauth/') {
714-
$url = $this->_endpoint_oauth . $method;
789+
if (substr($method, 0, 5) == 'oauth') {
790+
$url = self::$_endpoint_oauth . $method;
715791
} elseif ($this->_detectOld($method_template)) {
716-
$url = $this->_endpoint_old . $method . '.json';
792+
$url = self::$_endpoint_old . $method . '.json';
717793
} else {
718-
$url = $this->_endpoint . $method . '.json';
794+
$url = self::$_endpoint . $method . '.json';
719795
}
720796
return $url;
721797
}
@@ -728,22 +804,28 @@ private function _getEndpoint($method, $method_template)
728804
* @param string $method_template The templated API method to call
729805
* @param array optional $params The parameters to send along
730806
* @param bool optional $multipart Whether to use multipart/form-data
807+
* @param bool optional $app_only_auth Whether to use app-only bearer authentication
731808
*
732809
* @return mixed The API reply, encoded in the set return_format
733810
*/
734811

735-
private function _callApi($httpmethod, $method, $method_template, $params = array(), $multipart = false)
812+
private function _callApi($httpmethod, $method, $method_template, $params = array(), $multipart = false, $app_only_auth = false)
736813
{
737814
if (! function_exists('curl_init')) {
738815
throw new Exception('To make API requests, the PHP curl extension must be available.');
739816
}
740817
$url = $this->_getEndpoint($method, $method_template);
741818
$ch = false;
742819
if ($httpmethod == 'GET') {
743-
$ch = curl_init($this->_sign($httpmethod, $url, $params));
820+
$url_with_params = $url;
821+
if (count($params) > 0) {
822+
$url_with_params .= '?' . http_build_query($params);
823+
}
824+
$authorization = $this->_sign('GET', $url, $params);
825+
$ch = curl_init($url_with_params);
744826
} else {
745827
if ($multipart) {
746-
$authorization = $this->_sign('POST', $url, array(), true);
828+
$authorization = $this->_sign('POST', $url, array());
747829
$post_fields = $params;
748830
} else {
749831
$post_fields = $this->_sign('POST', $url, $params);
@@ -752,6 +834,16 @@ private function _callApi($httpmethod, $method, $method_template, $params = arra
752834
curl_setopt($ch, CURLOPT_POST, 1);
753835
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
754836
}
837+
if ($app_only_auth) {
838+
if (self::$_oauth_consumer_key == null) {
839+
throw new Exception('To make an app-only auth API request, the consumer key must be set.');
840+
}
841+
// automatically fetch bearer token, if necessary
842+
if (self::$_oauth_bearer_token == null) {
843+
$this->oauth2_token();
844+
}
845+
$authorization = 'Authorization: Bearer ' . self::$_oauth_bearer_token;
846+
}
755847
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
756848
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
757849
curl_setopt($ch, CURLOPT_HEADER, 1);

0 commit comments

Comments
 (0)
0