Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

token_storage.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 14.89 KiB


001  <?php
002  /**
003   *
004   * This file is part of the phpBB Forum Software package.
005   *
006   * @copyright (c) phpBB Limited <https://www.phpbb.com>
007   * @license GNU General Public License, version 2 (GPL-2.0)
008   *
009   * For full copyright and license information, please see
010   * the docs/CREDITS.txt file.
011   *
012   */
013   
014  namespace phpbb\auth\provider\oauth;
015   
016  use OAuth\OAuth1\Token\StdOAuth1Token;
017  use OAuth\Common\Token\TokenInterface;
018  use OAuth\Common\Storage\TokenStorageInterface;
019  use OAuth\Common\Storage\Exception\TokenNotFoundException;
020  use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
021   
022  /**
023   * OAuth storage wrapper for phpBB's cache
024   */
025  class token_storage implements TokenStorageInterface
026  {
027      /** @var \phpbb\db\driver\driver_interface */
028      protected $db;
029   
030      /** @var \phpbb\user */
031      protected $user;
032   
033      /** @var string OAuth table: token storage */
034      protected $oauth_token_table;
035   
036      /** @var string OAuth table: state */
037      protected $oauth_state_table;
038   
039      /** @var TokenInterface OAuth token */
040      protected $cachedToken;
041   
042      /** @var string OAuth state */
043      protected $cachedState;
044   
045      /**
046       * Constructor.
047       *
048       * @param \phpbb\db\driver\driver_interface    $db                    Database object
049       * @param \phpbb\user                        $user                User object
050       * @param string                            $oauth_token_table    OAuth table: token storage
051       * @param string                            $oauth_state_table    OAuth table: state
052       */
053      public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $oauth_token_table, $oauth_state_table)
054      {
055          $this->db    = $db;
056          $this->user    = $user;
057   
058          $this->oauth_token_table = $oauth_token_table;
059          $this->oauth_state_table = $oauth_state_table;
060      }
061   
062      /**
063       * {@inheritdoc}
064       */
065      public function retrieveAccessToken($service)
066      {
067          $service = $this->get_service_name_for_db($service);
068   
069          if ($this->cachedToken instanceof TokenInterface)
070          {
071              return $this->cachedToken;
072          }
073   
074          $data = [
075              'user_id'    => (int) $this->user->data['user_id'],
076              'provider'    => $service,
077          ];
078   
079          if ((int) $this->user->data['user_id'] === ANONYMOUS)
080          {
081              $data['session_id']    = $this->user->data['session_id'];
082          }
083   
084          return $this->_retrieve_access_token($data);
085      }
086   
087      /**
088       * {@inheritdoc}
089       */
090      public function storeAccessToken($service, TokenInterface $token)
091      {
092          $service = $this->get_service_name_for_db($service);
093   
094          $this->cachedToken = $token;
095   
096          $data = [
097              'oauth_token'    => $this->json_encode_token($token),
098          ];
099   
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  }
621