[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/auth/provider/oauth/ -> token_storage.php (source)

   1  <?php
   2  /**
   3   *
   4   * This file is part of the phpBB Forum Software package.
   5   *
   6   * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7   * @license GNU General Public License, version 2 (GPL-2.0)
   8   *
   9   * For full copyright and license information, please see
  10   * the docs/CREDITS.txt file.
  11   *
  12   */
  13  
  14  namespace phpbb\auth\provider\oauth;
  15  
  16  use OAuth\OAuth1\Token\StdOAuth1Token;
  17  use OAuth\Common\Token\TokenInterface;
  18  use OAuth\Common\Storage\TokenStorageInterface;
  19  use OAuth\Common\Storage\Exception\TokenNotFoundException;
  20  use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
  21  
  22  /**
  23   * OAuth storage wrapper for phpBB's cache
  24   */
  25  class token_storage implements TokenStorageInterface
  26  {
  27      /** @var \phpbb\db\driver\driver_interface */
  28      protected $db;
  29  
  30      /** @var \phpbb\user */
  31      protected $user;
  32  
  33      /** @var string OAuth table: token storage */
  34      protected $oauth_token_table;
  35  
  36      /** @var string OAuth table: state */
  37      protected $oauth_state_table;
  38  
  39      /** @var TokenInterface OAuth token */
  40      protected $cachedToken;
  41  
  42      /** @var string OAuth state */
  43      protected $cachedState;
  44  
  45      /**
  46       * Constructor.
  47       *
  48       * @param \phpbb\db\driver\driver_interface    $db                    Database object
  49       * @param \phpbb\user                        $user                User object
  50       * @param string                            $oauth_token_table    OAuth table: token storage
  51       * @param string                            $oauth_state_table    OAuth table: state
  52       */
  53  	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $oauth_token_table, $oauth_state_table)
  54      {
  55          $this->db    = $db;
  56          $this->user    = $user;
  57  
  58          $this->oauth_token_table = $oauth_token_table;
  59          $this->oauth_state_table = $oauth_state_table;
  60      }
  61  
  62      /**
  63       * {@inheritdoc}
  64       */
  65  	public function retrieveAccessToken($service)
  66      {
  67          $service = $this->get_service_name_for_db($service);
  68  
  69          if ($this->cachedToken instanceof TokenInterface)
  70          {
  71              return $this->cachedToken;
  72          }
  73  
  74          $data = [
  75              'user_id'    => (int) $this->user->data['user_id'],
  76              'provider'    => $service,
  77          ];
  78  
  79          if ((int) $this->user->data['user_id'] === ANONYMOUS)
  80          {
  81              $data['session_id']    = $this->user->data['session_id'];
  82          }
  83  
  84          return $this->_retrieve_access_token($data);
  85      }
  86  
  87      /**
  88       * {@inheritdoc}
  89       */
  90  	public function storeAccessToken($service, TokenInterface $token)
  91      {
  92          $service = $this->get_service_name_for_db($service);
  93  
  94          $this->cachedToken = $token;
  95  
  96          $data = [
  97              'oauth_token'    => $this->json_encode_token($token),
  98          ];
  99  
 100          $sql = 'UPDATE ' . $this->oauth_token_table . '
 101              SET ' . $this->db->sql_build_array('UPDATE', $data) . '
 102              WHERE user_id = ' . (int) $this->user->data['user_id'] . "
 103                  AND provider = '" . $this->db->sql_escape($service) . "'";
 104  
 105          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 106          {
 107              $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 108          }
 109  
 110          $this->db->sql_query($sql);
 111  
 112          if (!$this->db->sql_affectedrows())
 113          {
 114              $data = [
 115                  'user_id'        => (int) $this->user->data['user_id'],
 116                  'provider'        => $service,
 117                  'oauth_token'    => $this->json_encode_token($token),
 118                  'session_id'    => $this->user->data['session_id'],
 119              ];
 120  
 121              $sql = 'INSERT INTO ' . $this->oauth_token_table . $this->db->sql_build_array('INSERT', $data);
 122  
 123              $this->db->sql_query($sql);
 124          }
 125  
 126          return $this;
 127      }
 128  
 129      /**
 130       * {@inheritdoc}
 131       */
 132  	public function hasAccessToken($service)
 133      {
 134          $service = $this->get_service_name_for_db($service);
 135  
 136          if ($this->cachedToken)
 137          {
 138              return true;
 139          }
 140  
 141          $data = [
 142              'user_id'    => (int) $this->user->data['user_id'],
 143              'provider'    => $service,
 144          ];
 145  
 146          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 147          {
 148              $data['session_id']    = $this->user->data['session_id'];
 149          }
 150  
 151          return $this->has_access_token($data);
 152      }
 153  
 154      /**
 155       * {@inheritdoc}
 156       */
 157  	public function clearToken($service)
 158      {
 159          $service = $this->get_service_name_for_db($service);
 160  
 161          $this->cachedToken = null;
 162  
 163          $sql = 'DELETE FROM ' . $this->oauth_token_table . '
 164              WHERE user_id = ' . (int) $this->user->data['user_id'] . "
 165                  AND provider = '" . $this->db->sql_escape($service) . "'";
 166  
 167          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 168          {
 169              $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 170          }
 171  
 172          $this->db->sql_query($sql);
 173  
 174          return $this;
 175      }
 176  
 177      /**
 178       * {@inheritdoc}
 179       */
 180  	public function clearAllTokens()
 181      {
 182          $this->cachedToken = null;
 183  
 184          $sql = 'DELETE FROM ' . $this->oauth_token_table . '
 185              WHERE user_id = ' . (int) $this->user->data['user_id'];
 186  
 187          if ((int) $this->user->data['user_id'] === ANONYMOUS && isset($this->user->data['session_id']))
 188          {
 189              $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 190          }
 191  
 192          $this->db->sql_query($sql);
 193  
 194          return $this;
 195      }
 196  
 197      /**
 198       * {@inheritdoc}
 199       */
 200  	public function storeAuthorizationState($service, $state)
 201      {
 202          $service = $this->get_service_name_for_db($service);
 203  
 204          $this->cachedState = $state;
 205  
 206          $data = [
 207              'user_id'        => (int) $this->user->data['user_id'],
 208              'provider'        => $service,
 209              'oauth_state'    => $state,
 210              'session_id'    => $this->user->data['session_id'],
 211          ];
 212  
 213          $sql = 'INSERT INTO ' . $this->oauth_state_table . ' ' . $this->db->sql_build_array('INSERT', $data);
 214          $this->db->sql_query($sql);
 215  
 216          return $this;
 217      }
 218  
 219      /**
 220       * {@inheritdoc}
 221       */
 222  	public function hasAuthorizationState($service)
 223      {
 224          $service = $this->get_service_name_for_db($service);
 225  
 226          if ($this->cachedState)
 227          {
 228              return true;
 229          }
 230  
 231          $data = [
 232              'user_id'    => (int) $this->user->data['user_id'],
 233              'provider'    => $service,
 234          ];
 235  
 236          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 237          {
 238              $data['session_id']    = $this->user->data['session_id'];
 239          }
 240  
 241          return (bool) $this->get_state_row($data);
 242      }
 243  
 244      /**
 245       * {@inheritdoc}
 246       */
 247  	public function retrieveAuthorizationState($service)
 248      {
 249          $service = $this->get_service_name_for_db($service);
 250  
 251          if ($this->cachedState)
 252          {
 253              return $this->cachedState;
 254          }
 255  
 256          $data = [
 257              'user_id'    => (int) $this->user->data['user_id'],
 258              'provider'    => $service,
 259          ];
 260  
 261          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 262          {
 263              $data['session_id']    = $this->user->data['session_id'];
 264          }
 265  
 266          return $this->get_state_row($data);
 267      }
 268  
 269      /**
 270       * {@inheritdoc}
 271       */
 272  	public function clearAuthorizationState($service)
 273      {
 274          $service = $this->get_service_name_for_db($service);
 275  
 276          $this->cachedState = null;
 277  
 278          $sql = 'DELETE FROM ' . $this->oauth_state_table . '
 279              WHERE user_id = ' . (int) $this->user->data['user_id'] . "
 280                  AND provider = '" . $this->db->sql_escape($service) . "'";
 281  
 282          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 283          {
 284              $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 285          }
 286  
 287          $this->db->sql_query($sql);
 288  
 289          return $this;
 290      }
 291  
 292      /**
 293       * {@inheritdoc}
 294       */
 295  	public function clearAllAuthorizationStates()
 296      {
 297          $this->cachedState = null;
 298  
 299          $sql = 'DELETE FROM ' . $this->oauth_state_table . '
 300              WHERE user_id = ' . (int) $this->user->data['user_id'];
 301  
 302          if ((int) $this->user->data['user_id'] === ANONYMOUS)
 303          {
 304              $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 305          }
 306  
 307          $this->db->sql_query($sql);
 308  
 309          return $this;
 310      }
 311  
 312      /**
 313       * Updates the user_id field in the database associated with the token.
 314       *
 315       * @param int        $user_id    The user identifier
 316       * @return void
 317       */
 318  	public function set_user_id($user_id)
 319      {
 320          if (!$this->cachedToken)
 321          {
 322              return;
 323          }
 324  
 325          $data = [
 326              'user_id' => (int) $user_id,
 327          ];
 328  
 329          $sql = 'UPDATE ' . $this->oauth_token_table . '
 330              SET ' . $this->db->sql_build_array('UPDATE', $data) . '
 331              WHERE user_id = ' . (int) $this->user->data['user_id'] . "
 332                  AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
 333          $this->db->sql_query($sql);
 334      }
 335  
 336      /**
 337       * Checks to see if an access token exists solely by the session_id of the user.
 338       *
 339       * @param string    $service    The OAuth service name
 340       * @return bool                    true if the user's access token exists,
 341       *                                 false if the user's access token does not exist
 342       */
 343  	public function has_access_token_by_session($service)
 344      {
 345          $service = $this->get_service_name_for_db($service);
 346  
 347          if ($this->cachedToken)
 348          {
 349              return true;
 350          }
 351  
 352          $data = [
 353              'session_id'    => $this->user->data['session_id'],
 354              'provider'        => $service,
 355          ];
 356  
 357          return $this->has_access_token($data);
 358      }
 359  
 360      /**
 361       * Checks to see if a state exists solely by the session_id of the user.
 362       *
 363       * @param string    $service    The OAuth service name
 364       * @return bool                    true if the user's state exists,
 365       *                                 false if the user's state does not exist
 366       */
 367  	public function has_state_by_session($service)
 368      {
 369          $service = $this->get_service_name_for_db($service);
 370  
 371          if ($this->cachedState)
 372          {
 373              return true;
 374          }
 375  
 376          $data = [
 377              'session_id'    => $this->user->data['session_id'],
 378              'provider'        => $service,
 379          ];
 380  
 381          return (bool) $this->get_state_row($data);
 382      }
 383  
 384      /**
 385       * A helper function that performs the query for has access token functions.
 386       *
 387       * @param array        $data        The SQL WHERE data
 388       * @return bool                    true if the user's access token exists,
 389       *                                 false if the user's access token does not exist
 390       */
 391  	protected function has_access_token($data)
 392      {
 393          return (bool) $this->get_access_token_row($data);
 394      }
 395  
 396      /**
 397       * A helper function that performs the query for retrieving access token functions by session.
 398       * Also checks if the token is a valid token.
 399       *
 400       * @param string    $service    The OAuth service provider name
 401       * @return TokenInterface
 402       * @throws TokenNotFoundException
 403       */
 404  	public function retrieve_access_token_by_session($service)
 405      {
 406          $service = $this->get_service_name_for_db($service);
 407  
 408          if ($this->cachedToken instanceof TokenInterface)
 409          {
 410              return $this->cachedToken;
 411          }
 412  
 413          $data = [
 414              'session_id'    => $this->user->data['session_id'],
 415              'provider'        => $service,
 416          ];
 417  
 418          return $this->_retrieve_access_token($data);
 419      }
 420  
 421      /**
 422       * A helper function that performs the query for retrieving state functions by session.
 423       *
 424       * @param string    $service    The OAuth service provider name
 425       * @return string                The OAuth state
 426       * @throws AuthorizationStateNotFoundException
 427       */
 428  	public function retrieve_state_by_session($service)
 429      {
 430          $service = $this->get_service_name_for_db($service);
 431  
 432          if ($this->cachedState)
 433          {
 434              return $this->cachedState;
 435          }
 436  
 437          $data = [
 438              'session_id'    => $this->user->data['session_id'],
 439              'provider'        => $service,
 440          ];
 441  
 442          return $this->_retrieve_state($data);
 443      }
 444  
 445      /**
 446       * A helper function that performs the query for retrieve access token functions.
 447       * Also checks if the token is a valid token.
 448       *
 449       * @param array        $data        The SQL WHERE data
 450       * @return TokenInterface
 451       * @throws TokenNotFoundException
 452       */
 453  	protected function _retrieve_access_token($data)
 454      {
 455          $row = $this->get_access_token_row($data);
 456  
 457          if (!$row)
 458          {
 459              throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_NOT_STORED');
 460          }
 461  
 462          $token = $this->json_decode_token($row['oauth_token']);
 463  
 464          // Ensure that the token was serialized/unserialized correctly
 465          if (!($token instanceof TokenInterface))
 466          {
 467              $this->clearToken($data['provider']);
 468  
 469              throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED');
 470          }
 471  
 472          $this->cachedToken = $token;
 473  
 474          return $token;
 475      }
 476  
 477      /**
 478       * A helper function that performs the query for retrieve state functions.
 479       *
 480       * @param array        $data        The SQL WHERE data
 481       * @return string                The OAuth state
 482       * @throws AuthorizationStateNotFoundException
 483       */
 484  	protected function _retrieve_state($data)
 485      {
 486          $row = $this->get_state_row($data);
 487  
 488          if (!$row)
 489          {
 490              throw new AuthorizationStateNotFoundException();
 491          }
 492  
 493          $this->cachedState = $row['oauth_state'];
 494  
 495          return $this->cachedState;
 496      }
 497  
 498      /**
 499       * A helper function that performs the query for retrieving an access token.
 500       *
 501       * @param array        $data        The SQL WHERE data
 502       * @return array|false            array with the OAuth token row,
 503       *                               false if the token does not exist
 504       */
 505  	protected function get_access_token_row($data)
 506      {
 507          $sql = 'SELECT oauth_token
 508              FROM ' . $this->oauth_token_table . '
 509              WHERE ' . $this->db->sql_build_array('SELECT', $data);
 510          $result = $this->db->sql_query($sql);
 511          $row = $this->db->sql_fetchrow($result);
 512          $this->db->sql_freeresult($result);
 513  
 514          return $row;
 515      }
 516  
 517      /**
 518       * A helper function that performs the query for retrieving a state.
 519       *
 520       * @param array        $data        The SQL WHERE data
 521       * @return array|false            array with the OAuth state row,
 522       *                               false if the state does not exist
 523       */
 524  	protected function get_state_row($data)
 525      {
 526          $sql = 'SELECT oauth_state
 527              FROM ' . $this->oauth_state_table . '
 528              WHERE ' . $this->db->sql_build_array('SELECT', $data);
 529          $result = $this->db->sql_query($sql);
 530          $row = $this->db->sql_fetchrow($result);
 531          $this->db->sql_freeresult($result);
 532  
 533          return $row;
 534      }
 535  
 536      /**
 537       * A helper function that JSON encodes a TokenInterface's data.
 538       *
 539       * @param TokenInterface    $token
 540       * @return string                    The json encoded TokenInterface's data
 541       */
 542  	public function json_encode_token(TokenInterface $token)
 543      {
 544          $members = [
 545              'accessToken'    => $token->getAccessToken(),
 546              'endOfLife'        => $token->getEndOfLife(),
 547              'extraParams'    => $token->getExtraParams(),
 548              'refreshToken'    => $token->getRefreshToken(),
 549  
 550              'token_class'    => get_class($token),
 551          ];
 552  
 553          // Handle additional data needed for OAuth1 tokens
 554          if ($token instanceof StdOAuth1Token)
 555          {
 556              $members['requestToken']        = $token->getRequestToken();
 557              $members['requestTokenSecret']    = $token->getRequestTokenSecret();
 558              $members['accessTokenSecret']    = $token->getAccessTokenSecret();
 559          }
 560  
 561          return json_encode($members);
 562      }
 563  
 564      /**
 565       * A helper function that JSON decodes a data string and creates a TokenInterface.
 566       *
 567       * @param string    $json            The json encoded TokenInterface's data
 568       * @return TokenInterface
 569       * @throws TokenNotFoundException
 570       */
 571  	public function json_decode_token($json)
 572      {
 573          $token_data = json_decode($json, true);
 574  
 575          if ($token_data === null)
 576          {
 577              throw new TokenNotFoundException('AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED');
 578          }
 579  
 580          $token_class    = $token_data['token_class'];
 581          $access_token    = $token_data['accessToken'];
 582          $refresh_token    = $token_data['refreshToken'];
 583          $endOfLife        = $token_data['endOfLife'];
 584          $extra_params    = $token_data['extraParams'];
 585  
 586          /**
 587           * Create the token
 588           * @var TokenInterface    $token
 589           */
 590          $token = new $token_class($access_token, $refresh_token, TokenInterface::EOL_NEVER_EXPIRES, $extra_params);
 591          $token->setEndOfLife($endOfLife);
 592  
 593          // Handle OAuth 1.0 specific elements
 594          if ($token instanceof StdOAuth1Token)
 595          {
 596              $token->setRequestToken($token_data['requestToken']);
 597              $token->setRequestTokenSecret($token_data['requestTokenSecret']);
 598              $token->setAccessTokenSecret($token_data['accessTokenSecret']);
 599          }
 600  
 601          return $token;
 602      }
 603  
 604      /**
 605       * Returns the service name as it must be stored in the database.
 606       *
 607       * @param string    $provider    The OAuth provider name
 608       * @return string                The OAuth service name
 609       */
 610  	protected function get_service_name_for_db($provider)
 611      {
 612          // Enforce the naming convention for oauth services
 613          if (strpos($provider, 'auth.provider.oauth.service.') !== 0)
 614          {
 615              $provider = 'auth.provider.oauth.service.' . strtolower($provider);
 616          }
 617  
 618          return $provider;
 619      }
 620  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1