Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.
/lib/ -> oauthlib.php (source)

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  
  18  defined('MOODLE_INTERNAL') || die();
  19  
  20  require_once($CFG->libdir.'/filelib.php');
  21  
  22  /**
  23   * OAuth helper class
  24   *
  25   * 1. You can extends oauth_helper to add specific functions, such as twitter extends oauth_helper
  26   * 2. Call request_token method to get oauth_token and oauth_token_secret, and redirect user to authorize_url,
  27   *    developer needs to store oauth_token and oauth_token_secret somewhere, we will use them to request
  28   *    access token later on
  29   * 3. User approved the request, and get back to moodle
  30   * 4. Call get_access_token, it takes previous oauth_token and oauth_token_secret as arguments, oauth_token
  31   *    will be used in OAuth request, oauth_token_secret will be used to bulid signature, this method will
  32   *    return access_token and access_secret, store these two values in database or session
  33   * 5. Now you can access oauth protected resources by access_token and access_secret using oauth_helper::request
  34   *    method (or get() post())
  35   *
  36   * Note:
  37   * 1. This class only support HMAC-SHA1
  38   * 2. oauth_helper class don't store tokens and secrets, you must store them manually
  39   * 3. Some functions are based on http://code.google.com/p/oauth/
  40   *
  41   * @package    moodlecore
  42   * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
  43   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  44   */
  45  
  46  class oauth_helper {
  47      /** @var string consumer key, issued by oauth provider*/
  48      protected $consumer_key;
  49      /** @var string consumer secret, issued by oauth provider*/
  50      protected $consumer_secret;
  51      /** @var string oauth root*/
  52      protected $api_root;
  53      /** @var string request token url*/
  54      protected $request_token_api;
  55      /** @var string authorize url*/
  56      protected $authorize_url;
  57      protected $http_method;
  58      /** @var string */
  59      protected $access_token_api;
  60      /** @var curl */
  61      protected $http;
  62      /** @var array options to pass to the next curl request */
  63      protected $http_options;
  64      /** @var moodle_url oauth callback URL. */
  65      protected $oauth_callback;
  66       /** @var string access token. */
  67      protected $access_token;
  68      /** @var  string access secret token. */
  69      protected $access_token_secret;
  70      /** @var  string sign secret. */
  71      protected $sign_secret;
  72      /** @var  string nonce. */
  73      protected $nonce;
  74      /** @var  int timestamp. */
  75      protected $timestamp;
  76  
  77  
  78      /**
  79       * Contructor for oauth_helper.
  80       * Subclass can override construct to build its own $this->http
  81       *
  82       * @param array $args requires at least three keys, oauth_consumer_key
  83       *                    oauth_consumer_secret and api_root, oauth_helper will
  84       *                    guess request_token_api, authrize_url and access_token_api
  85       *                    based on api_root, but it not always works
  86       */
  87      function __construct($args) {
  88          if (!empty($args['api_root'])) {
  89              $this->api_root = $args['api_root'];
  90          } else {
  91              $this->api_root = '';
  92          }
  93          $this->consumer_key = $args['oauth_consumer_key'];
  94          $this->consumer_secret = $args['oauth_consumer_secret'];
  95  
  96          if (empty($args['request_token_api'])) {
  97              $this->request_token_api = $this->api_root . '/request_token';
  98          } else {
  99              $this->request_token_api = $args['request_token_api'];
 100          }
 101  
 102          if (empty($args['authorize_url'])) {
 103              $this->authorize_url = $this->api_root . '/authorize';
 104          } else {
 105              $this->authorize_url = $args['authorize_url'];
 106          }
 107  
 108          if (empty($args['access_token_api'])) {
 109              $this->access_token_api = $this->api_root . '/access_token';
 110          } else {
 111              $this->access_token_api = $args['access_token_api'];
 112          }
 113  
 114          if (!empty($args['oauth_callback'])) {
 115              $this->oauth_callback = new moodle_url($args['oauth_callback']);
 116          }
 117          if (!empty($args['access_token'])) {
 118              $this->access_token = $args['access_token'];
 119          }
 120          if (!empty($args['access_token_secret'])) {
 121              $this->access_token_secret = $args['access_token_secret'];
 122          }
 123          $this->http = new curl(array('debug'=>false));
 124          if (!empty($args['http_options'])) {
 125              $this->http_options = $args['http_options'];
 126          } else {
 127              $this->http_options = array();
 128          }
 129      }
 130  
 131      /**
 132       * Build parameters list:
 133       *    oauth_consumer_key="0685bd9184jfhq22",
 134       *    oauth_nonce="4572616e48616d6d65724c61686176",
 135       *    oauth_token="ad180jjd733klru7",
 136       *    oauth_signature_method="HMAC-SHA1",
 137       *    oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
 138       *    oauth_timestamp="137131200",
 139       *    oauth_version="1.0"
 140       *    oauth_verifier="1.0"
 141       * @param array $param
 142       * @return string
 143       */
 144      function get_signable_parameters($params){
 145          $sorted = $params;
 146          ksort($sorted);
 147  
 148          $total = array();
 149          foreach ($sorted as $k => $v) {
 150              if ($k == 'oauth_signature') {
 151                  continue;
 152              }
 153  
 154              $total[] = rawurlencode($k) . '=' . rawurlencode($v);
 155          }
 156          return implode('&', $total);
 157      }
 158  
 159      /**
 160       * Create signature for oauth request
 161       * @param string $url
 162       * @param string $secret
 163       * @param array $params
 164       * @return string
 165       */
 166      public function sign($http_method, $url, $params, $secret) {
 167          $sig = array(
 168              strtoupper($http_method),
 169              preg_replace('/%7E/', '~', rawurlencode($url)),
 170              rawurlencode($this->get_signable_parameters($params)),
 171          );
 172  
 173          $base_string = implode('&', $sig);
 174          $sig = base64_encode(hash_hmac('sha1', $base_string, $secret, true));
 175          return $sig;
 176      }
 177  
 178      /**
 179       * Initilize oauth request parameters, including:
 180       *    oauth_consumer_key="0685bd9184jfhq22",
 181       *    oauth_token="ad180jjd733klru7",
 182       *    oauth_signature_method="HMAC-SHA1",
 183       *    oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
 184       *    oauth_timestamp="137131200",
 185       *    oauth_nonce="4572616e48616d6d65724c61686176",
 186       *    oauth_version="1.0"
 187       * To access protected resources, oauth_token should be defined
 188       *
 189       * @param string $url
 190       * @param string $token
 191       * @param string $http_method
 192       * @return array
 193       */
 194      public function prepare_oauth_parameters($url, $params, $http_method = 'POST') {
 195          if (is_array($params)) {
 196              $oauth_params = $params;
 197          } else {
 198              $oauth_params = array();
 199          }
 200          $oauth_params['oauth_version']	     = '1.0';
 201          $oauth_params['oauth_nonce']	     = $this->get_nonce();
 202          $oauth_params['oauth_timestamp']    = $this->get_timestamp();
 203          $oauth_params['oauth_consumer_key'] = $this->consumer_key;
 204          $oauth_params['oauth_signature_method']	 = 'HMAC-SHA1';
 205          $oauth_params['oauth_signature']	 = $this->sign($http_method, $url, $oauth_params, $this->sign_secret);
 206          return $oauth_params;
 207      }
 208  
 209      public function setup_oauth_http_header($params) {
 210  
 211          $total = array();
 212          ksort($params);
 213          foreach ($params as $k => $v) {
 214              $total[] = rawurlencode($k) . '="' . rawurlencode($v).'"';
 215          }
 216          $str = implode(', ', $total);
 217          $str = 'Authorization: OAuth '.$str;
 218          $this->http->setHeader('Expect:');
 219          $this->http->setHeader($str);
 220      }
 221  
 222      /**
 223       * Sets the options for the next curl request
 224       *
 225       * @param array $options
 226       */
 227      public function setup_oauth_http_options($options) {
 228          $this->http_options = $options;
 229      }
 230  
 231      /**
 232       * Request token for authentication
 233       * This is the first step to use OAuth, it will return oauth_token and oauth_token_secret
 234       * @return array
 235       */
 236      public function request_token() {
 237          $this->sign_secret = $this->consumer_secret.'&';
 238  
 239          if (empty($this->oauth_callback)) {
 240              $params = [];
 241          } else {
 242              $params = ['oauth_callback' => $this->oauth_callback->out(false)];
 243          }
 244  
 245          $params = $this->prepare_oauth_parameters($this->request_token_api, $params, 'GET');
 246          $content = $this->http->get($this->request_token_api, $params, $this->http_options);
 247          // Including:
 248          //     oauth_token
 249          //     oauth_token_secret
 250          $result = $this->parse_result($content);
 251          if (empty($result['oauth_token'])) {
 252              throw new moodle_exception('oauth1requesttoken', 'core_error', '', null, $content);
 253          }
 254          // Build oauth authorize url.
 255          $result['authorize_url'] = $this->authorize_url . '?oauth_token='.$result['oauth_token'];
 256  
 257          return $result;
 258      }
 259  
 260      /**
 261       * Set oauth access token for oauth request
 262       * @param string $token
 263       * @param string $secret
 264       */
 265      public function set_access_token($token, $secret) {
 266          $this->access_token = $token;
 267          $this->access_token_secret = $secret;
 268      }
 269  
 270      /**
 271       * Request oauth access token from server
 272       * @param string $method
 273       * @param string $url
 274       * @param string $token
 275       * @param string $secret
 276       */
 277      public function get_access_token($token, $secret, $verifier='') {
 278          $this->sign_secret = $this->consumer_secret.'&'.$secret;
 279          $params = $this->prepare_oauth_parameters($this->access_token_api, array('oauth_token'=>$token, 'oauth_verifier'=>$verifier), 'POST');
 280          $this->setup_oauth_http_header($params);
 281          // Should never send the callback in this request.
 282          unset($params['oauth_callback']);
 283          $content = $this->http->post($this->access_token_api, $params, $this->http_options);
 284          $keys = $this->parse_result($content);
 285  
 286          if (empty($keys['oauth_token']) || empty($keys['oauth_token_secret'])) {
 287              throw new moodle_exception('oauth1accesstoken', 'core_error', '', null, $content);
 288          }
 289  
 290          $this->set_access_token($keys['oauth_token'], $keys['oauth_token_secret']);
 291          return $keys;
 292      }
 293  
 294      /**
 295       * Request oauth protected resources
 296       * @param string $method
 297       * @param string $url
 298       * @param string $token
 299       * @param string $secret
 300       */
 301      public function request($method, $url, $params=array(), $token='', $secret='') {
 302          if (empty($token)) {
 303              $token = $this->access_token;
 304          }
 305          if (empty($secret)) {
 306              $secret = $this->access_token_secret;
 307          }
 308          // to access protected resource, sign_secret will alwasy be consumer_secret+token_secret
 309          $this->sign_secret = $this->consumer_secret.'&'.$secret;
 310          if (strtolower($method) === 'post' && !empty($params)) {
 311              $oauth_params = $this->prepare_oauth_parameters($url, array('oauth_token'=>$token) + $params, $method);
 312          } else {
 313              $oauth_params = $this->prepare_oauth_parameters($url, array('oauth_token'=>$token), $method);
 314          }
 315          $this->setup_oauth_http_header($oauth_params);
 316          $content = call_user_func_array(array($this->http, strtolower($method)), array($url, $params, $this->http_options));
 317          // reset http header and options to prepare for the next request
 318          $this->http->resetHeader();
 319          // return request return value
 320          return $content;
 321      }
 322  
 323      /**
 324       * shortcut to start http get request
 325       */
 326      public function get($url, $params=array(), $token='', $secret='') {
 327          return $this->request('GET', $url, $params, $token, $secret);
 328      }
 329  
 330      /**
 331       * shortcut to start http post request
 332       */
 333      public function post($url, $params=array(), $token='', $secret='') {
 334          return $this->request('POST', $url, $params, $token, $secret);
 335      }
 336  
 337      /**
 338       * A method to parse oauth response to get oauth_token and oauth_token_secret
 339       * @param string $str
 340       * @return array
 341       */
 342      public function parse_result($str) {
 343          if (empty($str)) {
 344              throw new moodle_exception('error');
 345          }
 346          $parts = explode('&', $str);
 347          $result = array();
 348          foreach ($parts as $part){
 349              list($k, $v) = explode('=', $part, 2);
 350              $result[urldecode($k)] = urldecode($v);
 351          }
 352          if (empty($result)) {
 353              throw new moodle_exception('error');
 354          }
 355          return $result;
 356      }
 357  
 358      /**
 359       * Set nonce
 360       */
 361      function set_nonce($str) {
 362          $this->nonce = $str;
 363      }
 364      /**
 365       * Set timestamp
 366       */
 367      function set_timestamp($time) {
 368          $this->timestamp = $time;
 369      }
 370      /**
 371       * Generate timestamp
 372       */
 373      function get_timestamp() {
 374          if (!empty($this->timestamp)) {
 375              $timestamp = $this->timestamp;
 376              unset($this->timestamp);
 377              return $timestamp;
 378          }
 379          return time();
 380      }
 381      /**
 382       * Generate nonce for oauth request
 383       */
 384      function get_nonce() {
 385          if (!empty($this->nonce)) {
 386              $nonce = $this->nonce;
 387              unset($this->nonce);
 388              return $nonce;
 389          }
 390          $mt = microtime();
 391          $rand = mt_rand();
 392  
 393          return md5($mt . $rand);
 394      }
 395  }
 396  
 397  /**
 398   * OAuth 2.0 Client for using web access tokens.
 399   *
 400   * http://tools.ietf.org/html/draft-ietf-oauth-v2-22
 401   *
 402   * @package   core
 403   * @copyright Dan Poltawski <talktodan@gmail.com>
 404   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 405   */
 406  abstract class oauth2_client extends curl {
 407      /** @var string $clientid client identifier issued to the client */
 408      private $clientid = '';
 409      /** @var string $clientsecret The client secret. */
 410      private $clientsecret = '';
 411      /** @var moodle_url $returnurl URL to return to after authenticating */
 412      private $returnurl = null;
 413      /** @var string $scope of the authentication request */
 414      protected $scope = '';
 415      /** @var stdClass $accesstoken access token object */
 416      protected $accesstoken = null;
 417      /** @var string $refreshtoken refresh token string */
 418      protected $refreshtoken = '';
 419      /** @var string $mocknextresponse string */
 420      private $mocknextresponse = '';
 421      /** @var array $upgradedcodes list of upgraded codes in this request */
 422      private static $upgradedcodes = [];
 423      /** @var bool basicauth */
 424      protected $basicauth = false;
 425  
 426      /**
 427       * Returns the auth url for OAuth 2.0 request
 428       * @return string the auth url
 429       */
 430      abstract protected function auth_url();
 431  
 432      /**
 433       * Returns the token url for OAuth 2.0 request
 434       * @return string the auth url
 435       */
 436      abstract protected function token_url();
 437  
 438      /**
 439       * Constructor.
 440       *
 441       * @param string $clientid
 442       * @param string $clientsecret
 443       * @param moodle_url $returnurl
 444       * @param string $scope
 445       */
 446      public function __construct($clientid, $clientsecret, moodle_url $returnurl, $scope) {
 447          parent::__construct();
 448          $this->clientid = $clientid;
 449          $this->clientsecret = $clientsecret;
 450          $this->returnurl = $returnurl;
 451          $this->scope = $scope;
 452          $this->accesstoken = $this->get_stored_token();
 453      }
 454  
 455      /**
 456       * Is the user logged in? Note that if this is called
 457       * after the first part of the authorisation flow the token
 458       * is upgraded to an accesstoken.
 459       *
 460       * @return boolean true if logged in
 461       */
 462      public function is_logged_in() {
 463          // Has the token expired?
 464          if (isset($this->accesstoken->expires) && time() >= $this->accesstoken->expires) {
 465              $this->store_token(null);
 466              return false;
 467          }
 468  
 469          // We have a token so we are logged in.
 470          if (isset($this->accesstoken->token)) {
 471              // Check that the access token has all the requested scopes.
 472              $scopemissing = false;
 473              $scopecheck = ' ' . $this->accesstoken->scope . ' ';
 474  
 475              $requiredscopes = explode(' ', $this->scope);
 476              foreach ($requiredscopes as $requiredscope) {
 477                  if (strpos($scopecheck, ' ' . $requiredscope . ' ') === false) {
 478                      $scopemissing = true;
 479                      break;
 480                  }
 481              }
 482              if (!$scopemissing) {
 483                  return true;
 484              }
 485          }
 486  
 487          // If we've been passed then authorization code generated by the
 488          // authorization server try and upgrade the token to an access token.
 489          $code = optional_param('oauth2code', null, PARAM_RAW);
 490          // Note - sometimes we may call is_logged_in twice in the same request - we don't want to attempt
 491          // to upgrade the same token twice.
 492          if ($code && !in_array($code, self::$upgradedcodes) && $this->upgrade_token($code)) {
 493              return true;
 494          }
 495  
 496          return false;
 497      }
 498  
 499      /**
 500       * Callback url where the request is returned to.
 501       *
 502       * @return moodle_url url of callback
 503       */
 504      public static function callback_url() {
 505          global $CFG;
 506  
 507          return new moodle_url('/admin/oauth2callback.php');
 508      }
 509  
 510      /**
 511       * An additional array of url params to pass with a login request.
 512       *
 513       * @return array of name value pairs.
 514       */
 515      public function get_additional_login_parameters() {
 516          return [];
 517      }
 518  
 519      /**
 520       * Returns the login link for this oauth request
 521       *
 522       * @return moodle_url login url
 523       */
 524      public function get_login_url() {
 525  
 526          $callbackurl = self::callback_url();
 527          $defaultparams = [
 528              'client_id' => $this->clientid,
 529              'response_type' => 'code',
 530              'redirect_uri' => $callbackurl->out(false),
 531              'state' => $this->returnurl->out_as_local_url(false),
 532  
 533          ];
 534          if (!empty($this->scope)) {
 535              // The scope should only be included if a value is set.
 536              // If none provided, the server MUST process the request and provide an appropriate documented response.
 537              // See spec https://tools.ietf.org/html/rfc6749#section-3.3
 538              $defaultparams['scope'] = $this->scope;
 539          }
 540  
 541          $params = array_merge(
 542              $defaultparams,
 543              $this->get_additional_login_parameters()
 544          );
 545  
 546          return new moodle_url($this->auth_url(), $params);
 547      }
 548  
 549      /**
 550       * Given an array of name value pairs - build a valid HTTP POST application/x-www-form-urlencoded string.
 551       *
 552       * @param array $params Name / value pairs.
 553       * @return string POST data.
 554       */
 555      public function build_post_data($params) {
 556          $result = [];
 557          foreach ($params as $name => $value) {
 558              $result[] = urlencode($name) . '=' . urlencode($value);
 559          }
 560          return implode('&', $result);
 561      }
 562  
 563      /**
 564       * Upgrade a authorization token from oauth 2.0 to an access token
 565       *
 566       * @param string $code the code returned from the oauth authenticaiton
 567       * @return boolean true if token is upgraded succesfully
 568       */
 569      public function upgrade_token($code) {
 570          $callbackurl = self::callback_url();
 571          $params = array('code' => $code,
 572              'grant_type' => 'authorization_code',
 573              'redirect_uri' => $callbackurl->out(false),
 574          );
 575  
 576          if ($this->basicauth) {
 577              $idsecret = urlencode($this->clientid) . ':' . urlencode($this->clientsecret);
 578              $this->setHeader('Authorization: Basic ' . base64_encode($idsecret));
 579          } else {
 580              $params['client_id'] = $this->clientid;
 581              $params['client_secret'] = $this->clientsecret;
 582          }
 583  
 584          // Requests can either use http GET or POST.
 585          if ($this->use_http_get()) {
 586              $response = $this->get($this->token_url(), $params);
 587          } else {
 588              $response = $this->post($this->token_url(), $this->build_post_data($params));
 589          }
 590  
 591          if ($this->info['http_code'] !== 200) {
 592              $debuginfo = !empty($this->error) ? $this->error : $response;
 593              throw new moodle_exception('oauth2upgradetokenerror', 'core_error', '', $this->info['http_code'], $debuginfo);
 594          }
 595  
 596          $r = json_decode($response);
 597  
 598          if (is_null($r)) {
 599              throw new moodle_exception("Could not decode JSON token response");
 600          }
 601  
 602          if (!empty($r->error)) {
 603              throw new moodle_exception($r->error . ' ' . $r->error_description);
 604          }
 605  
 606          if (!isset($r->access_token)) {
 607              return false;
 608          }
 609  
 610          if (isset($r->refresh_token)) {
 611              $this->refreshtoken = $r->refresh_token;
 612          }
 613  
 614          // Store the token an expiry time.
 615          $accesstoken = new stdClass;
 616          $accesstoken->token = $r->access_token;
 617          if (isset($r->expires_in)) {
 618              // Expires 10 seconds before actual expiry.
 619              $accesstoken->expires = (time() + ($r->expires_in - 10));
 620          }
 621          $accesstoken->scope = $this->scope;
 622          // Also add the scopes.
 623          self::$upgradedcodes[] = $code;
 624          $this->store_token($accesstoken);
 625  
 626          return true;
 627      }
 628  
 629      /**
 630       * Logs out of a oauth request, clearing any stored tokens
 631       */
 632      public function log_out() {
 633          $this->store_token(null);
 634      }
 635  
 636      /**
 637       * Make a HTTP request, adding the access token we have
 638       *
 639       * @param string $url The URL to request
 640       * @param array $options
 641       * @param mixed $acceptheader mimetype (as string) or false to skip sending an accept header.
 642       * @return bool
 643       */
 644      protected function request($url, $options = array(), $acceptheader = 'application/json') {
 645          $murl = new moodle_url($url);
 646  
 647          if ($this->accesstoken) {
 648              if ($this->use_http_get()) {
 649                  // If using HTTP GET add as a parameter.
 650                  $murl->param('access_token', $this->accesstoken->token);
 651              } else {
 652                  $this->setHeader('Authorization: Bearer '.$this->accesstoken->token);
 653              }
 654          }
 655  
 656          if ($acceptheader) {
 657              $this->setHeader('Accept: ' . $acceptheader);
 658          }
 659  
 660          $response = parent::request($murl->out(false), $options);
 661  
 662          $this->resetHeader();
 663  
 664          return $response;
 665      }
 666  
 667      /**
 668       * Multiple HTTP Requests
 669       * This function could run multi-requests in parallel.
 670       *
 671       * @param array $requests An array of files to request
 672       * @param array $options An array of options to set
 673       * @return array An array of results
 674       */
 675      protected function multi($requests, $options = array()) {
 676          if ($this->accesstoken) {
 677              $this->setHeader('Authorization: Bearer '.$this->accesstoken->token);
 678          }
 679          return parent::multi($requests, $options);
 680      }
 681  
 682      /**
 683       * Returns the tokenname for the access_token to be stored
 684       * through multiple requests.
 685       *
 686       * The default implentation is to use the classname combiend
 687       * with the scope.
 688       *
 689       * @return string tokenname for prefernce storage
 690       */
 691      protected function get_tokenname() {
 692          // This is unusual but should work for most purposes.
 693          return get_class($this).'-'.md5($this->scope);
 694      }
 695  
 696      /**
 697       * Store a token between requests. Currently uses
 698       * session named by get_tokenname
 699       *
 700       * @param stdClass|null $token token object to store or null to clear
 701       */
 702      protected function store_token($token) {
 703          global $SESSION;
 704  
 705          $this->accesstoken = $token;
 706          $name = $this->get_tokenname();
 707  
 708          if ($token !== null) {
 709              $SESSION->{$name} = $token;
 710          } else {
 711              unset($SESSION->{$name});
 712          }
 713      }
 714  
 715      /**
 716       * Get a refresh token!!!
 717       *
 718       * @return string
 719       */
 720      public function get_refresh_token() {
 721          return $this->refreshtoken;
 722      }
 723  
 724      /**
 725       * Retrieve a token stored.
 726       *
 727       * @return stdClass|null token object
 728       */
 729      protected function get_stored_token() {
 730          global $SESSION;
 731  
 732          $name = $this->get_tokenname();
 733  
 734          if (isset($SESSION->{$name})) {
 735              return $SESSION->{$name};
 736          }
 737  
 738          return null;
 739      }
 740  
 741      /**
 742       * Get access token object.
 743       *
 744       * This is just a getter to read the private property.
 745       *
 746       * @return stdClass
 747       */
 748      public function get_accesstoken() {
 749          return $this->accesstoken;
 750      }
 751  
 752      /**
 753       * Get the client ID.
 754       *
 755       * This is just a getter to read the private property.
 756       *
 757       * @return string
 758       */
 759      public function get_clientid() {
 760          return $this->clientid;
 761      }
 762  
 763      /**
 764       * Get the client secret.
 765       *
 766       * This is just a getter to read the private property.
 767       *
 768       * @return string
 769       */
 770      public function get_clientsecret() {
 771          return $this->clientsecret;
 772      }
 773  
 774      /**
 775       * Should HTTP GET be used instead of POST?
 776       * Some APIs do not support POST and want oauth to use
 777       * GET instead (with the auth_token passed as a GET param).
 778       *
 779       * @return bool true if GET should be used
 780       */
 781      protected function use_http_get() {
 782          return false;
 783      }
 784  }