PageRenderTime 95ms CodeModel.GetById 33ms RepoModel.GetById 2ms app.codeStats 0ms

/atk4-addons/misc/lib/Controller/OAuth.php

https://github.com/git86/todo
PHP | 309 lines | 278 code | 12 blank | 19 comment | 25 complexity | 5c353a5f0b847c41456291e61bde0d41 MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. class Controller_OAuth extends AbstractController {
  3. protected $ch; //curl handler
  4. protected $sign_method = "RSA-SHA1"; // also supported are: PLAINTEXT and HMAC-SHA1
  5. protected $certfile; // required for RSA-SHA1
  6. protected $consumer_key; // required for all types
  7. protected $request_token_baseurl; // url for retreiving request token
  8. protected $access_token_baseurl; // url for exchanging tokens
  9. protected $authorize_token_baseurl; // url for token authorization
  10. protected $callback_url; // callback url
  11. protected $error_callback_url; // error calback url
  12. protected $type='abstract'; // redefine in childs
  13. function init(){
  14. parent::init();
  15. // $this->setCallbackURL($this->api->getDestinationURL(null,
  16. // array('oauth'=>$this->name)));
  17. // Default URL :)
  18. }
  19. function check(){
  20. /* This function will perform calls to getAuthToken() etc
  21. */
  22. $this->setCallbackUrl(
  23. $this->api->getDestinationURL(null,array(
  24. 'auth'=>$this->name,'callback'=>1))
  25. );
  26. $this->setSignatureInfo();
  27. if(($_GET['auth']==$this->name && $_GET["callback"]) || !$_GET["auth"]){
  28. return $this->getAuthToken();
  29. }
  30. }
  31. function isLoggedIn(){
  32. if ($token = $this->recall("oauth-access-token")){
  33. return true;
  34. } else {
  35. return false;
  36. }
  37. }
  38. function setSignatureInfo(){
  39. /* redefine per actual implementation */
  40. /* by default assumes MHAC-SHA1 */
  41. $this->setConsumerKey($this->api->getConfig('oauth/'.$this->type.'/consumer/key'));
  42. $this->setConsumerSecret($this->api->getConfig('oauth/'.$this->type.'/consumer/secret'));
  43. $this->setSignMethod("HMAC-SHA1");
  44. }
  45. function logout(){
  46. $this->resetAuthToken();
  47. }
  48. function resetAuthToken(){
  49. $this->forget("oauth-access-token");
  50. $this->forget("oauth-request-token");
  51. }
  52. function getAuthToken($full = true){
  53. if ($oauth_token = $_GET["oauth_token"]){
  54. $oauth_verifier = $_GET["oauth_verifier"];
  55. try {
  56. $this->obtainAccessToken($oauth_token, $oauth_verifier);
  57. $this->api->redirect($this->callback_url);
  58. } catch (Exception $e){
  59. $this->callback_error_url->setArguments(array("error_msg" => $e->getMessage()));
  60. $this->api->redirect($this->callback_error_url);
  61. }
  62. exit;
  63. }
  64. if ($token = $this->recall("oauth-access-token")){
  65. if ($full){
  66. return $token;
  67. } else {
  68. return $token["oauth_token"];
  69. }
  70. } else {
  71. $this->obtainRequestToken();
  72. $this->authorizeToken();
  73. }
  74. }
  75. function getAuthTokenSecret(){
  76. if (isset($this->use_request_token)){
  77. $oauth = $this->recall("oauth-request-token");
  78. } else {
  79. $oauth = $this->recall("oauth-access-token");
  80. }
  81. return $oauth["oauth_token_secret"];
  82. }
  83. function getRequestTokenSecret(){
  84. $oauth = $this->recall("oauth-request-token");
  85. return $oauth["oauth_token_secret"];
  86. }
  87. function setAuthToken($oauth_token, $oauth_token_secret = null){
  88. $this->memorize("oauth-access-token",
  89. array(
  90. "oauth_token" => $auth_token,
  91. "auth_token_secret" => $oauth_token_secret
  92. )
  93. );
  94. }
  95. function setSignMethod($method){
  96. /* supported: RSA-SHA1, PLAINTEXT */
  97. $this->sign_method = $method;
  98. }
  99. function signRequest($method, $baseurl, array $parameters){
  100. /*
  101. * $method = GET | POST
  102. * $baseurl = "https://www.google.com/accounts/OAuth...";
  103. * $parameters = "extra parameters"
  104. */
  105. if (method_exists($this, $sign_method = "signRequest" . preg_replace("/[^a-zA-Z0-9]+/", "", $this->sign_method))){
  106. return $this->$sign_method($method, $baseurl, $parameters);
  107. }
  108. }
  109. function signRequestPLAINTEXT($method, $baseurl, array $parameters){
  110. return $this->consumer_secret . "&" . $this->getAuthTokenSecret();
  111. }
  112. function signRequestHMACSHA1($method, $baseurl, array $parameters){
  113. $data = $this->createSignatureBase($method, $baseurl, $parameters);
  114. $sign = hash_hmac("sha1", $data, $raw=$this->consumer_secret . "&" . $this->getAuthTokenSecret(), true);
  115. return base64_encode($sign);
  116. }
  117. function signRequestRSASHA1($method, $baseurl, array $parameters){
  118. $fp = @fopen($this->certfile, "r");
  119. if (!$fp){
  120. throw new Exception("Could not read certificate file");
  121. }
  122. $private = fread($fp, 8192);
  123. fclose($fp);
  124. $data = $this->createSignatureBase($method, $baseurl, $parameters);
  125. $keyid = openssl_get_privatekey($private);
  126. openssl_sign($data, $signature, $keyid);
  127. openssl_free_key($keyid);
  128. return base64_encode($signature);
  129. }
  130. function encodeStr($str){
  131. return preg_replace("/\%7E/", "~", urlencode($str));
  132. }
  133. function createSignatureBase($method, $baseurl, array $parameters){
  134. $data = $method.'&';
  135. $data .= $this->encodeStr($baseurl).'&';
  136. $oauth = '';
  137. ksort($parameters);
  138. foreach($parameters as $key => $value){
  139. $oauth .= "&{$key}={$value}";
  140. }
  141. $data .= urlencode(substr($oauth, 1));
  142. return $data;
  143. }
  144. function buildAuthArray($baseurl, $extra = array(), $method = 'GET'){
  145. /*
  146. * All $extra params should be urlencoded!
  147. */
  148. $auth = array();
  149. $baseurl = preg_replace("/\?.*$/", "", $baseurl);
  150. $auth['oauth_consumer_key'] = $this->consumer_key;
  151. $auth['oauth_signature_method'] = $this->sign_method;
  152. $auth['oauth_timestamp'] = time();
  153. $auth['oauth_nonce'] = md5(uniqid(rand(), true));
  154. $auth['oauth_version'] = '1.0';
  155. $auth = array_merge($auth, is_array($extra)?$extra:array());
  156. $auth['oauth_signature'] = $this->signRequest($method, $baseurl, $auth);
  157. $auth['oauth_signature'] = urlencode($auth['oauth_signature']);
  158. return $auth;
  159. }
  160. function setCallbackURL($callback_url, $callback_error_url=null){
  161. if($callback_url instanceof URL){
  162. $callback_url->useAbsoluteURL();
  163. if(!$callback_error_url){
  164. $callback_error_url=clone $callback_url;
  165. $callback_error_url
  166. ->setArguments(array('error'=>1));
  167. }
  168. }
  169. if(!$callback_error_url){
  170. throw new BaseException
  171. ('Specify error_url or use URL class');
  172. }
  173. $this->callback_url=$callback_url;
  174. $this->callback_error_url=$callback_error_url;
  175. }
  176. function setConsumerKey($consumer_key){
  177. $this->consumer_key = $consumer_key;
  178. }
  179. function setConsumerSecret($consumer_secret){
  180. $this->consumer_secret = $consumer_secret;
  181. }
  182. function setCertFile($certfile){
  183. $this->certfile = $certfile;
  184. }
  185. function useRequestToken(){
  186. /* this is needed when exchanging tokens and using HMAC-RSA signature method */
  187. $this->use_request_token = true;
  188. }
  189. function obtainAccessToken($oauth_token, $oauth_verifier = null){
  190. $params = array("oauth_token" => urlencode($oauth_token));
  191. if ($oauth_verifier){
  192. $params["oauth_verifier"] = urlencode($oauth_verifier);
  193. }
  194. $this->useRequestToken();
  195. $response = $this->performRequest($this->access_token_baseurl, $params);
  196. $response = explode("&", $response);
  197. $data = array();
  198. foreach ($response as $row){
  199. $row = explode("=", $row);
  200. $data[$row[0]] = $row[1];
  201. }
  202. if (isset($data["oauth_token_secret"])){
  203. $this->memorize("oauth-access-token", $data);
  204. } else {
  205. throw new Exception("Could not fetch access token");
  206. }
  207. return $data;
  208. }
  209. function authorizeToken(){
  210. $token_data = $this->recall("oauth-request-token", array());
  211. if ($token_data){
  212. $u=$this->add('URL')
  213. ->setBaseURL($this->authorize_token_baseurl)
  214. ->setArguments(array(
  215. 'oauth_token'=>$token_data['oauth_token'],
  216. 'oauth_callback'=>$this->callback_url
  217. ));
  218. $this->api->redirect($u);
  219. }
  220. }
  221. function obtainRequestToken($extra = array()){
  222. $extra["oauth_callback"] = urlencode($this->callback_url->getURL());
  223. $response = $this->performRequest($this->request_token_baseurl, $extra);
  224. $response = explode("&", $response);
  225. $data = array();
  226. foreach ($response as $row){
  227. $row = explode("=", $row);
  228. $data[$row[0]] = $row[1];
  229. }
  230. $this->preProcessRequestToken($data);
  231. $this->memorize("oauth-request-token", $data);
  232. return $data;
  233. }
  234. function preProcessRequestToken(&$data){
  235. $data["oauth_token"] = urldecode($data["oauth_token"]);
  236. }
  237. function performRequest($url, $extra = array()){
  238. $this->curlInit($url);
  239. $auth = $this->buildAuthArray($url, $extra);
  240. $this->setCurlAuthHeader($auth);
  241. $response = $this->executeCurl();
  242. return $response;
  243. }
  244. function performPostRequest($url, $extra_header = array(), $extra_auth = array(), $post = array()){
  245. $this->curlInit($url, "POST");
  246. $auth = $this->buildAuthArray($url, $extra_auth, "POST");
  247. $this->setCurlAuthHeader($auth, $extra_header);
  248. $this->curlSetPost($post);
  249. $response = $this->executeCurl();
  250. return $response;
  251. }
  252. function createAuthHeader($auth){
  253. $str = array();
  254. foreach($auth as $k => $v){
  255. $str[] = "{$k}=\"{$v}\"";
  256. }
  257. $str = implode(", ", $str);
  258. return $str;
  259. }
  260. /* curl methods */
  261. function curlInit($url, $method = "GET"){
  262. $this->ch=curl_init();
  263. curl_setopt($this->ch, CURLOPT_URL, $url);
  264. curl_setopt($this->ch, CURLOPT_VERBOSE, true);
  265. //curl_setopt($this->ch, CURLOPT_STDERR, fopen("curlerr.log", "a"));
  266. curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
  267. curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
  268. curl_setopt($this->ch, CURLOPT_SSLVERSION,3);
  269. curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  270. curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 2);
  271. curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
  272. if ($method == "POST"){
  273. curl_setopt($this->ch, CURLOPT_POST, 1);
  274. }
  275. return $this;
  276. }
  277. function curlSetPost($data){
  278. curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
  279. }
  280. function setCurlAuthHeader($auth, $extra = null){
  281. $auth_header = $this->createAuthHeader($auth);
  282. curl_setopt($this->ch, CURLOPT_HTTPHEADER, $t = array_merge(array("Authorization: OAuth {$auth_header}"),
  283. is_array($extra)?$extra:array()));
  284. return $this;
  285. }
  286. function executeCurl(){
  287. $response = curl_exec($this->ch);
  288. $st = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
  289. if ($st < 200 || $st >= 300){
  290. $this->last_error = $response;
  291. throw new Exception("Could not process request ($st)" . $response, $st);
  292. }
  293. return $response;
  294. }
  295. function render(){
  296. }
  297. }