diff options
Diffstat (limited to 'phpBB/phpbb/auth')
-rw-r--r-- | phpBB/phpbb/auth/auth.php | 42 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/base.php | 2 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/db.php | 1 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/ldap.php | 9 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/oauth/oauth.php | 115 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/oauth/service/twitter.php | 102 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/oauth/token_storage.php | 261 | ||||
-rw-r--r-- | phpBB/phpbb/auth/provider/provider_interface.php | 6 |
8 files changed, 494 insertions, 44 deletions
diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php index b59f0e60ec..f46a21a8ae 100644 --- a/phpBB/phpbb/auth/auth.php +++ b/phpBB/phpbb/auth/auth.php @@ -72,8 +72,8 @@ class auth // Verify bitstring length with options provided... $renew = false; - $global_length = sizeof($this->acl_options['global']); - $local_length = sizeof($this->acl_options['local']); + $global_length = count($this->acl_options['global']); + $local_length = count($this->acl_options['local']); // Specify comparing length (bitstring is padded to 31 bits) $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length; @@ -236,7 +236,7 @@ class auth $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE; - if (sizeof($this->acl)) + if (count($this->acl)) { $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true); } @@ -278,7 +278,7 @@ class auth } // If we get forum_ids not having this permission, we need to fill the remaining parts - if ($negate && sizeof($this->acl_forum_ids)) + if ($negate && count($this->acl_forum_ids)) { foreach ($this->acl_forum_ids as $f) { @@ -455,7 +455,7 @@ class auth { $hold_str = ''; - if (sizeof($hold_ary)) + if (count($hold_ary)) { ksort($hold_ary); @@ -514,7 +514,7 @@ class auth */ function acl_clear_prefetch($user_id = false) { - global $db, $cache; + global $db, $cache, $phpbb_dispatcher; // Rebuild options cache $cache->destroy('_role_cache'); @@ -553,6 +553,16 @@ class auth $where_sql"; $db->sql_query($sql); + /** + * Event is triggered after user(s) permission settings cache has been cleared + * + * @event core.acl_clear_prefetch_after + * @var mixed user_id User ID(s) + * @since 3.1.11-RC1 + */ + $vars = array('user_id'); + extract($phpbb_dispatcher->trigger_event('core.acl_clear_prefetch_after', compact($vars))); + return; } @@ -928,7 +938,9 @@ class auth function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0) { global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container; + global $phpbb_dispatcher; + /* @var $provider_collection \phpbb\auth\provider_collection */ $provider_collection = $phpbb_container->get('auth.provider_collection'); $provider = $provider_collection->get_provider(); @@ -982,6 +994,24 @@ class auth redirect($url); } + /** + * Event is triggered after checking for valid username and password, and before the actual session creation. + * + * @event core.auth_login_session_create_before + * @var array login Variable containing login array + * @var bool admin Boolean variable whether user is logging into the ACP + * @var string username Username of user to log in + * @var bool autologin Boolean variable signaling whether login is triggered via auto login + * @since 3.1.7-RC1 + */ + $vars = array( + 'login', + 'admin', + 'username', + 'autologin', + ); + extract($phpbb_dispatcher->trigger_event('core.auth_login_session_create_before', compact($vars))); + // If login succeeded, we will log the user in... else we pass the login array through... if ($login['status'] == LOGIN_SUCCESS) { diff --git a/phpBB/phpbb/auth/provider/base.php b/phpBB/phpbb/auth/provider/base.php index 4c49070eaf..dea27ccc25 100644 --- a/phpBB/phpbb/auth/provider/base.php +++ b/phpBB/phpbb/auth/provider/base.php @@ -61,7 +61,7 @@ abstract class base implements \phpbb\auth\provider\provider_interface /** * {@inheritdoc} */ - public function get_auth_link_data() + public function get_auth_link_data($user_id = 0) { return; } diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index d8c5fb72de..1adf85ee05 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -155,6 +155,7 @@ class db extends \phpbb\auth\provider\base // Every auth module is able to define what to do by itself... if ($show_captcha) { + /* @var $captcha_factory \phpbb\captcha\factory */ $captcha_factory = $this->phpbb_container->get('captcha.factory'); $captcha = $captcha_factory->get_instance($this->config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index d32e7504eb..0789a6234d 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -99,7 +99,7 @@ class ldap extends \phpbb\auth\provider\base @ldap_close($ldap); - if (!is_array($result) || sizeof($result) < 2) + if (!is_array($result) || count($result) < 2) { return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']); } @@ -192,7 +192,7 @@ class ldap extends \phpbb\auth\provider\base $ldap_result = @ldap_get_entries($ldap, $search); - if (is_array($ldap_result) && sizeof($ldap_result) > 1) + if (is_array($ldap_result) && count($ldap_result) > 1) { if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password))) { @@ -289,7 +289,6 @@ class ldap extends \phpbb\auth\provider\base /** * {@inheritdoc} */ - public function acp() { // These are fields required in the config table @@ -306,9 +305,9 @@ class ldap extends \phpbb\auth\provider\base return array( 'TEMPLATE_FILE' => 'auth_provider_ldap.html', 'TEMPLATE_VARS' => array( - 'AUTH_LDAP_DN' => $new_config['ldap_base_dn'], + 'AUTH_LDAP_BASE_DN' => $new_config['ldap_base_dn'], 'AUTH_LDAP_EMAIL' => $new_config['ldap_email'], - 'AUTH_LDAP_PASSORD' => $new_config['ldap_password'], + 'AUTH_LDAP_PASSORD' => $new_config['ldap_password'] !== '' ? '********' : '', 'AUTH_LDAP_PORT' => $new_config['ldap_port'], 'AUTH_LDAP_SERVER' => $new_config['ldap_server'], 'AUTH_LDAP_UID' => $new_config['ldap_uid'], diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index c0ce3f1fba..8809a0c6b4 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -63,6 +63,13 @@ class oauth extends \phpbb\auth\provider\base protected $auth_provider_oauth_token_storage_table; /** + * OAuth state table + * + * @var string + */ + protected $auth_provider_oauth_state_table; + + /** * OAuth account association table * * @var string @@ -98,6 +105,13 @@ class oauth extends \phpbb\auth\provider\base protected $phpbb_container; /** + * phpBB event dispatcher + * + * @var \phpbb\event\dispatcher_interface + */ + protected $dispatcher; + + /** * phpBB root path * * @var string @@ -120,14 +134,16 @@ class oauth extends \phpbb\auth\provider\base * @param \phpbb\request\request_interface $request * @param \phpbb\user $user * @param string $auth_provider_oauth_token_storage_table + * @param string $auth_provider_oauth_state_table * @param string $auth_provider_oauth_token_account_assoc * @param \phpbb\di\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface * @param string $users_table * @param \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container DI container + * @param \phpbb\event\dispatcher_interface $dispatcher phpBB event dispatcher * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_state_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; @@ -135,10 +151,12 @@ class oauth extends \phpbb\auth\provider\base $this->request = $request; $this->user = $user; $this->auth_provider_oauth_token_storage_table = $auth_provider_oauth_token_storage_table; + $this->auth_provider_oauth_state_table = $auth_provider_oauth_state_table; $this->auth_provider_oauth_token_account_assoc = $auth_provider_oauth_token_account_assoc; $this->service_providers = $service_providers; $this->users_table = $users_table; $this->phpbb_container = $phpbb_container; + $this->dispatcher = $dispatcher; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; } @@ -188,11 +206,12 @@ class oauth extends \phpbb\auth\provider\base // Get the service credentials for the given service $service_credentials = $this->service_providers[$service_name]->get_service_credentials(); - $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); $query = 'mode=login&login=external&oauth_service=' . $service_name_original; $service = $this->get_service($service_name_original, $storage, $service_credentials, $query, $this->service_providers[$service_name]->get_auth_scope()); - if ($this->request->is_set('code', \phpbb\request\request_interface::GET)) + if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET)) + || ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET))) { $this->service_providers[$service_name]->set_external_service_provider($service); $unique_id = $this->service_providers[$service_name]->perform_auth_login(); @@ -208,6 +227,22 @@ class oauth extends \phpbb\auth\provider\base $row = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); + /** + * Event is triggered before check if provider is already associated with an account + * + * @event core.oauth_login_after_check_if_provider_id_has_match + * @var array row User row + * @var array data Provider data + * @var \OAuth\Common\Service\ServiceInterface service OAuth service + * @since 3.2.3-RC1 + */ + $vars = array( + 'row', + 'data', + 'service', + ); + extract($this->dispatcher->trigger_event('core.oauth_login_after_check_if_provider_id_has_match', compact($vars))); + if (!$row) { // The user does not yet exist, ask to link or create profile @@ -238,6 +273,18 @@ class oauth extends \phpbb\auth\provider\base // Update token storage to store the user_id $storage->set_user_id($row['user_id']); + /** + * Event is triggered after user is successfuly logged in via OAuth. + * + * @event core.auth_oauth_login_after + * @var array row User row + * @since 3.1.11-RC1 + */ + $vars = array( + 'row', + ); + extract($this->dispatcher->trigger_event('core.auth_oauth_login_after', compact($vars))); + // The user is now authenticated and can be logged in return array( 'status' => LOGIN_SUCCESS, @@ -247,7 +294,15 @@ class oauth extends \phpbb\auth\provider\base } else { - $url = $service->getAuthorizationUri(); + if ($service::OAUTH_VERSION === 1) + { + $token = $service->requestRequestToken(); + $url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken())); + } + else + { + $url = $service->getAuthorizationUri(); + } header('Location: ' . $url); } } @@ -271,7 +326,13 @@ class oauth extends \phpbb\auth\provider\base } $uri_factory = new \OAuth\Common\Http\Uri\UriFactory(); - $current_uri = $uri_factory->createFromSuperGlobalArray($this->request->get_super_global(\phpbb\request\request_interface::SERVER)); + $super_globals = $this->request->get_super_global(\phpbb\request\request_interface::SERVER); + if (!empty($super_globals['HTTP_X_FORWARDED_PROTO']) && $super_globals['HTTP_X_FORWARDED_PROTO'] === 'https') + { + $super_globals['HTTPS'] = 'on'; + $super_globals['SERVER_PORT'] = 443; + } + $current_uri = $uri_factory->createFromSuperGlobalArray($super_globals); $current_uri->setQuery($query); $this->current_uri = $current_uri; @@ -456,7 +517,7 @@ class oauth extends \phpbb\auth\provider\base */ protected function link_account_login_link(array $link_data, $service_name) { - $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); // Check for an access token, they should have one if (!$storage->has_access_token_by_session($service_name)) @@ -499,13 +560,14 @@ class oauth extends \phpbb\auth\provider\base */ protected function link_account_auth_link(array $link_data, $service_name) { - $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); $query = 'i=ucp_auth_link&mode=auth_link&link=1&oauth_service=' . strtolower($link_data['oauth_service']); $service_credentials = $this->service_providers[$service_name]->get_service_credentials(); $scopes = $this->service_providers[$service_name]->get_auth_scope(); $service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes); - if ($this->request->is_set('code', \phpbb\request\request_interface::GET)) + if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET)) + || ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET))) { $this->service_providers[$service_name]->set_external_service_provider($service); $unique_id = $this->service_providers[$service_name]->perform_auth_login(); @@ -521,7 +583,15 @@ class oauth extends \phpbb\auth\provider\base } else { - $url = $service->getAuthorizationUri(); + if ($service::OAUTH_VERSION === 1) + { + $token = $service->requestRequestToken(); + $url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken())); + } + else + { + $url = $service->getAuthorizationUri(); + } header('Location: ' . $url); } } @@ -536,6 +606,18 @@ class oauth extends \phpbb\auth\provider\base $sql = 'INSERT INTO ' . $this->auth_provider_oauth_token_account_assoc . ' ' . $this->db->sql_build_array('INSERT', $data); $this->db->sql_query($sql); + + /** + * Event is triggered after user links account. + * + * @event core.auth_oauth_link_after + * @var array data User row + * @since 3.1.11-RC1 + */ + $vars = array( + 'data', + ); + extract($this->dispatcher->trigger_event('core.auth_oauth_link_after', compact($vars))); } /** @@ -544,7 +626,7 @@ class oauth extends \phpbb\auth\provider\base public function logout($data, $new_session) { // Clear all tokens belonging to the user - $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); $storage->clearAllTokens(); return; @@ -553,13 +635,13 @@ class oauth extends \phpbb\auth\provider\base /** * {@inheritdoc} */ - public function get_auth_link_data() + public function get_auth_link_data($user_id = 0) { $block_vars = array(); // Get all external accounts tied to the current user $data = array( - 'user_id' => (int) $this->user->data['user_id'], + 'user_id' => ($user_id <= 0) ? (int) $this->user->data['user_id'] : (int) $user_id, ); $sql = 'SELECT oauth_provider_id, provider FROM ' . $this->auth_provider_oauth_token_account_assoc . ' WHERE ' . $this->db->sql_build_array('SELECT', $data); @@ -569,7 +651,7 @@ class oauth extends \phpbb\auth\provider\base $oauth_user_ids = array(); - if ($rows !== false && sizeof($rows)) + if ($rows !== false && count($rows)) { foreach ($rows as $row) { @@ -616,15 +698,18 @@ class oauth extends \phpbb\auth\provider\base return 'LOGIN_LINK_MISSING_DATA'; } + // Remove user specified in $link_data if possible + $user_id = isset($link_data['user_id']) ? $link_data['user_id'] : $this->user->data['user_id']; + // Remove the link $sql = 'DELETE FROM ' . $this->auth_provider_oauth_token_account_assoc . " WHERE provider = '" . $this->db->sql_escape($link_data['oauth_service']) . "' - AND user_id = " . (int) $this->user->data['user_id']; + AND user_id = " . (int) $user_id; $this->db->sql_query($sql); // Clear all tokens belonging to the user on this servce $service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); - $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table); + $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); $storage->clearToken($service_name); } } diff --git a/phpBB/phpbb/auth/provider/oauth/service/twitter.php b/phpBB/phpbb/auth/provider/oauth/service/twitter.php new file mode 100644 index 0000000000..06beac51e2 --- /dev/null +++ b/phpBB/phpbb/auth/provider/oauth/service/twitter.php @@ -0,0 +1,102 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\auth\provider\oauth\service; + +/** +* Twitter OAuth service +*/ +class twitter extends \phpbb\auth\provider\oauth\service\base +{ + /** + * phpBB config + * + * @var \phpbb\config\config + */ + protected $config; + + /** + * phpBB request + * + * @var \phpbb\request\request_interface + */ + protected $request; + + /** + * Constructor + * + * @param \phpbb\config\config $config + * @param \phpbb\request\request_interface $request + */ + public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request) + { + $this->config = $config; + $this->request = $request; + } + + /** + * {@inheritdoc} + */ + public function get_service_credentials() + { + return array( + 'key' => $this->config['auth_oauth_twitter_key'], + 'secret' => $this->config['auth_oauth_twitter_secret'], + ); + } + + /** + * {@inheritdoc} + */ + public function perform_auth_login() + { + if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter)) + { + throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + $storage = $this->service_provider->getStorage(); + $token = $storage->retrieveAccessToken('Twitter'); + $tokensecret = $token->getRequestTokenSecret(); + + // This was a callback request from twitter, get the token + $this->service_provider->requestAccessToken( + $this->request->variable('oauth_token', ''), + $this->request->variable('oauth_verifier', ''), + $tokensecret + ); + + // Send a request with it + $result = json_decode($this->service_provider->request('account/verify_credentials.json'), true); + + // Return the unique identifier returned from twitter + return $result['id']; + } + + /** + * {@inheritdoc} + */ + public function perform_token_auth() + { + if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter)) + { + throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE'); + } + + // Send a request with it + $result = json_decode($this->service_provider->request('account/verify_credentials.json'), true); + + // Return the unique identifier returned from twitter + return $result['id']; + } +} diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php index 023cf402ca..b0c2fd0d62 100644 --- a/phpBB/phpbb/auth/provider/oauth/token_storage.php +++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php @@ -13,11 +13,11 @@ namespace phpbb\auth\provider\oauth; - use OAuth\OAuth1\Token\StdOAuth1Token; use OAuth\Common\Token\TokenInterface; use OAuth\Common\Storage\TokenStorageInterface; use OAuth\Common\Storage\Exception\TokenNotFoundException; +use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException; /** * OAuth storage wrapper for phpbb's cache @@ -43,7 +43,14 @@ class token_storage implements TokenStorageInterface * * @var string */ - protected $auth_provider_oauth_table; + protected $oauth_token_table; + + /** + * OAuth state table + * + * @var string + */ + protected $oauth_state_table; /** * @var object|TokenInterface @@ -51,17 +58,24 @@ class token_storage implements TokenStorageInterface protected $cachedToken; /** + * @var string + */ + protected $cachedState; + + /** * Creates token storage for phpBB. * * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\user $user - * @param string $auth_provider_oauth_table + * @param string $oauth_token_table + * @param string $oauth_state_table */ - public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $auth_provider_oauth_table) + public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $oauth_token_table, $oauth_state_table) { $this->db = $db; $this->user = $user; - $this->auth_provider_oauth_table = $auth_provider_oauth_table; + $this->oauth_token_table = $oauth_token_table; + $this->oauth_state_table = $oauth_state_table; } /** @@ -99,15 +113,31 @@ class token_storage implements TokenStorageInterface $this->cachedToken = $token; $data = array( - 'user_id' => (int) $this->user->data['user_id'], - 'provider' => $service, 'oauth_token' => $this->json_encode_token($token), - 'session_id' => $this->user->data['session_id'], ); - $sql = 'INSERT INTO ' . $this->auth_provider_oauth_table . ' - ' . $this->db->sql_build_array('INSERT', $data); + $sql = 'UPDATE ' . $this->oauth_token_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $data) . ' + WHERE user_id = ' . (int) $this->user->data['user_id'] . ' + ' . ((int) $this->user->data['user_id'] === ANONYMOUS ? "AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'" : '') . " + AND provider = '" . $this->db->sql_escape($service) . "'"; $this->db->sql_query($sql); + + if (!$this->db->sql_affectedrows()) + { + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + 'oauth_token' => $this->json_encode_token($token), + 'session_id' => $this->user->data['session_id'], + ); + + $sql = 'INSERT INTO ' . $this->oauth_token_table . $this->db->sql_build_array('INSERT', $data); + + $this->db->sql_query($sql); + } + + return $this; } /** @@ -117,7 +147,8 @@ class token_storage implements TokenStorageInterface { $service = $this->get_service_name_for_db($service); - if ($this->cachedToken) { + if ($this->cachedToken) + { return true; } @@ -143,7 +174,7 @@ class token_storage implements TokenStorageInterface $this->cachedToken = null; - $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . ' + $sql = 'DELETE FROM ' . $this->oauth_token_table . ' WHERE user_id = ' . (int) $this->user->data['user_id'] . " AND provider = '" . $this->db->sql_escape($service) . "'"; @@ -153,6 +184,8 @@ class token_storage implements TokenStorageInterface } $this->db->sql_query($sql); + + return $this; } /** @@ -162,7 +195,123 @@ class token_storage implements TokenStorageInterface { $this->cachedToken = null; - $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . ' + $sql = 'DELETE FROM ' . $this->oauth_token_table . ' + WHERE user_id = ' . (int) $this->user->data['user_id']; + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; + } + + $this->db->sql_query($sql); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function storeAuthorizationState($service, $state) + { + $service = $this->get_service_name_for_db($service); + + $this->cachedState = $state; + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + 'oauth_state' => $state, + 'session_id' => $this->user->data['session_id'], + ); + + $sql = 'INSERT INTO ' . $this->oauth_state_table . ' + ' . $this->db->sql_build_array('INSERT', $data); + $this->db->sql_query($sql); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function hasAuthorizationState($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedState) + { + return true; + } + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + ); + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $data['session_id'] = $this->user->data['session_id']; + } + + return (bool) $this->get_state_row($data); + } + + /** + * {@inheritdoc} + */ + public function retrieveAuthorizationState($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedState) + { + return $this->cachedState; + } + + $data = array( + 'user_id' => (int) $this->user->data['user_id'], + 'provider' => $service, + ); + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $data['session_id'] = $this->user->data['session_id']; + } + + return $this->get_state_row($data); + } + + /** + * {@inheritdoc} + */ + public function clearAuthorizationState($service) + { + $service = $this->get_service_name_for_db($service); + + $this->cachedState = null; + + $sql = 'DELETE FROM ' . $this->oauth_state_table . ' + WHERE user_id = ' . (int) $this->user->data['user_id'] . " + AND provider = '" . $this->db->sql_escape($service) . "'"; + + if ((int) $this->user->data['user_id'] === ANONYMOUS) + { + $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'"; + } + + $this->db->sql_query($sql); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function clearAllAuthorizationStates() + { + $this->cachedState = null; + + $sql = 'DELETE FROM ' . $this->oauth_state_table . ' WHERE user_id = ' . (int) $this->user->data['user_id']; if ((int) $this->user->data['user_id'] === ANONYMOUS) @@ -171,6 +320,8 @@ class token_storage implements TokenStorageInterface } $this->db->sql_query($sql); + + return $this; } /** @@ -185,7 +336,7 @@ class token_storage implements TokenStorageInterface return; } - $sql = 'UPDATE ' . $this->auth_provider_oauth_table . ' + $sql = 'UPDATE ' . $this->oauth_token_table . ' SET ' . $this->db->sql_build_array('UPDATE', array( 'user_id' => (int) $user_id )) . ' @@ -218,6 +369,29 @@ class token_storage implements TokenStorageInterface } /** + * Checks to see if a state exists solely by the session_id of the user + * + * @param string $service The name of the OAuth service + * @return bool true if they have state, false if they don't + */ + public function has_state_by_session($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedState) + { + return true; + } + + $data = array( + 'session_id' => $this->user->data['session_id'], + 'provider' => $service, + ); + + return (bool) $this->get_state_row($data); + } + + /** * A helper function that performs the query for has access token functions * * @param array $data @@ -232,7 +406,8 @@ class token_storage implements TokenStorageInterface { $service = $this->get_service_name_for_db($service); - if ($this->cachedToken instanceof TokenInterface) { + if ($this->cachedToken instanceof TokenInterface) + { return $this->cachedToken; } @@ -244,6 +419,23 @@ class token_storage implements TokenStorageInterface return $this->_retrieve_access_token($data); } + public function retrieve_state_by_session($service) + { + $service = $this->get_service_name_for_db($service); + + if ($this->cachedState) + { + return $this->cachedState; + } + + $data = array( + 'session_id' => $this->user->data['session_id'], + 'provider' => $service, + ); + + return $this->_retrieve_state($data); + } + /** * A helper function that performs the query for retrieve access token functions * Also checks if the token is a valid token @@ -275,6 +467,26 @@ class token_storage implements TokenStorageInterface } /** + * A helper function that performs the query for retrieve state functions + * + * @param array $data + * @return mixed + * @throws \OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException + */ + protected function _retrieve_state($data) + { + $row = $this->get_state_row($data); + + if (!$row) + { + throw new AuthorizationStateNotFoundException(); + } + + $this->cachedState = $row['oauth_state']; + return $this->cachedState; + } + + /** * A helper function that performs the query for retrieving an access token * * @param array $data @@ -282,7 +494,24 @@ class token_storage implements TokenStorageInterface */ protected function get_access_token_row($data) { - $sql = 'SELECT oauth_token FROM ' . $this->auth_provider_oauth_table . ' + $sql = 'SELECT oauth_token FROM ' . $this->oauth_token_table . ' + WHERE ' . $this->db->sql_build_array('SELECT', $data); + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + return $row; + } + + /** + * A helper function that performs the query for retrieving a state + * + * @param array $data + * @return mixed + */ + protected function get_state_row($data) + { + $sql = 'SELECT oauth_state FROM ' . $this->oauth_state_table . ' WHERE ' . $this->db->sql_build_array('SELECT', $data); $result = $this->db->sql_query($sql); $row = $this->db->sql_fetchrow($result); diff --git a/phpBB/phpbb/auth/provider/provider_interface.php b/phpBB/phpbb/auth/provider/provider_interface.php index 613297cefc..35e0f559a1 100644 --- a/phpBB/phpbb/auth/provider/provider_interface.php +++ b/phpBB/phpbb/auth/provider/provider_interface.php @@ -166,6 +166,10 @@ interface provider_interface /** * Returns an array of data necessary to build the ucp_auth_link page * + * @param int $user_id User ID for whom the data should be retrieved. + * defaults to 0, which is not a valid ID. The method + * should fall back to the current user's ID in this + * case. * @return array|null If this function is not implemented on an auth * provider then it returns null. If it is implemented * it will return an array of up to four elements of @@ -181,7 +185,7 @@ interface provider_interface * 'VARS' => array(...), * ) */ - public function get_auth_link_data(); + public function get_auth_link_data($user_id = 0); /** * Unlinks an external account from a phpBB account. |