1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-01-18 06:38:43 +01:00

[ticket/14250] Change token_storage class to fit changed interface

PHPBB3-14250
This commit is contained in:
Oliver Schramm 2015-10-23 02:44:41 +02:00
parent e738dad729
commit 8ed59fb82a
7 changed files with 302 additions and 18 deletions

View File

@ -58,6 +58,7 @@ services:
- '@request'
- '@user'
- '%tables.auth_provider_oauth_token_storage%'
- '%tables.auth_provider_oauth_states%'
- '%tables.auth_provider_oauth_account_assoc%'
- '@auth.provider.oauth.service_collection'
- '%tables.users%'

View File

@ -6,6 +6,7 @@ parameters:
tables.acl_users: '%core.table_prefix%acl_users'
tables.attachments: '%core.table_prefix%attachments'
tables.auth_provider_oauth_token_storage: '%core.table_prefix%oauth_tokens'
tables.auth_provider_oauth_states: '%core.table_prefix%oauth_states'
tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts'
tables.banlist: '%core.table_prefix%banlist'
tables.bbcodes: '%core.table_prefix%bbcodes'

View File

@ -62,6 +62,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
*
@ -120,6 +127,7 @@ 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
@ -127,7 +135,7 @@ class oauth extends \phpbb\auth\provider\base
* @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_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
@ -135,6 +143,7 @@ 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;
@ -188,7 +197,7 @@ 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());
@ -456,7 +465,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,7 +508,7 @@ 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();
@ -544,7 +553,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;
@ -627,7 +636,7 @@ class oauth extends \phpbb\auth\provider\base
// 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);
}
}

View File

@ -17,6 +17,7 @@ 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
@ -42,25 +43,39 @@ 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
*/
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;
}
/**
@ -104,9 +119,11 @@ class token_storage implements TokenStorageInterface
'session_id' => $this->user->data['session_id'],
);
$sql = 'INSERT INTO ' . $this->auth_provider_oauth_table . '
$sql = 'INSERT INTO ' . $this->oauth_token_table . '
' . $this->db->sql_build_array('INSERT', $data);
$this->db->sql_query($sql);
return $this;
}
/**
@ -143,7 +160,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 +170,8 @@ class token_storage implements TokenStorageInterface
}
$this->db->sql_query($sql);
return $this;
}
/**
@ -162,7 +181,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'];
if ((int) $this->user->data['user_id'] === ANONYMOUS)
@ -171,6 +190,124 @@ class token_storage implements TokenStorageInterface
}
$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)
{
$sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
}
$this->db->sql_query($sql);
return $this;
}
/**
@ -185,7 +322,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
)) . '
@ -217,6 +354,29 @@ class token_storage implements TokenStorageInterface
return $this->_has_acess_token($data);
}
/**
* 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
*
@ -245,6 +405,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 +452,26 @@ class token_storage implements TokenStorageInterface
return $token;
}
/**
* 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
*
@ -283,7 +480,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);

View File

@ -0,0 +1,56 @@
<?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\db\migration\data\v320;
class oauth_states extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\auth_provider_oauth');
}
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'oauth_states');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'oauth_states' => array(
'COLUMNS' => array(
'user_id' => array('UINT', 0),
'session_id' => array('CHAR:32', ''),
'provider' => array('VCHAR', ''),
'oauth_state' => array('VCHAR', ''),
),
'KEYS' => array(
'user_id' => array('INDEX', 'user_id'),
'provider' => array('INDEX', 'provider'),
),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'oauth_states',
),
);
}
}

View File

@ -22,6 +22,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
protected $session_id;
protected $token_storage;
protected $token_storage_table;
protected $state_table;
protected $user;
protected function setup()
@ -36,6 +37,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
$this->user = new \phpbb\user($lang, '\phpbb\datetime');
$this->service_name = 'auth.provider.oauth.service.testing';
$this->token_storage_table = 'phpbb_oauth_tokens';
$this->state_table = 'phpbb_oauth_states';
// Give the user a session_id that we will remember
$this->session_id = '12345';
@ -44,7 +46,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
// Set the user id to anonymous
$this->user->data['user_id'] = ANONYMOUS;
$this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
$this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
}
public function getDataSet()
@ -98,7 +100,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);
// Store a token in the database
$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
$temp_storage->storeAccessToken($this->service_name, $expected_token);
unset($temp_storage);
@ -129,7 +131,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);
// Store a token in the database
$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
$temp_storage->storeAccessToken($this->service_name, $expected_token);
unset($temp_storage);

View File

@ -68,6 +68,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case
$request,
$user,
'phpbb_oauth_tokens',
'phpbb_oauth_states',
'phpbb_oauth_accounts',
$oauth_provider_collection,
'phpbb_users',