Skip to content

Commit

Permalink
Release 2.4.0 (#98)
Browse files Browse the repository at this point in the history
Issue #95 feat: Allow User Impersonation
If a user is not allowed to use impersonation, throw an error instead of falling back to the token user.
  • Loading branch information
coolbung authored Apr 13, 2019
1 parent 5903c5d commit b407202
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 15 deletions.
19 changes: 15 additions & 4 deletions code/plugins/system/tjtokenlogin/tjtokenlogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@

defined('_JEXEC') or die('Unauthorized Access');

require_once JPATH_SITE . '/components/com_api/vendors/php-jwt/src/JWT.php';
require_once JPATH_SITE . '/components/com_api/vendors/php-jwt/src/BeforeValidException.php';
require_once JPATH_SITE . '/components/com_api/vendors/php-jwt/src/ExpiredException.php';
require_once JPATH_SITE . '/components/com_api/vendors/php-jwt/src/SignatureInvalidException.php';
jimport('joomla.filesystem.file');

$jwtBasePath = JPATH_SITE . '/components/com_api/vendors/php-jwt/src';
$jwtFilePath = $jwtBasePath . '/JWT.php';

if (!JFile::exists($jwtFilePath))
{
return;
}

JLoader::import('JWT', $jwtBasePath);
JLoader::import('DomainException', $jwtBasePath);
JLoader::import('InvalidArgumentException', $jwtBasePath);
JLoader::import('UnexpectedValueException', $jwtBasePath);
JLoader::import('DateTime', $jwtBasePath);

use Firebase\JWT\JWT;
use Firebase\JWT\DomainException;
Expand Down
5 changes: 3 additions & 2 deletions code/site/language/en-GB/en-GB.com_api.ini
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ COM_API_ACCESS_SPECIAL="Special"
COM_API_SUCCESS="Success"
COM_API_UNEXPECTED_ERROR="Unexpected error ocurred"
COM_API_KEY_CREATE_UNAUTORIZED="You are not authorized to create API keys, please contact your administrator."

;vishal - for j3.2
COM_API_METHOD_NALLOW="This method not allowed"

; Since __DEPLOY_VERSION__
COM_API_INVALID_USER_TO_IMPERSONATE="Invalid user to impersonate"
116 changes: 116 additions & 0 deletions code/site/libraries/authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,120 @@ private static function getAuthorizationHeader()

return $headers;
}

/**
* Find if the user is trying impersonate other user
*
* @return int|string|NULL User id or Email id or null
*
* @since __DEPLOY_VERSION__
*/
public static function getImpersonateHeader()
{
$jinput = JFactory::getApplication()->input;
$xImpersonate = $jinput->server->get('X-Impersonate', '', 'STRING');
$httpXImpersonate = $jinput->server->get('HTTP_X_IMPERSONATE', '', 'STRING');

if (!empty($xImpersonate))
{
return $xImpersonate;
}
elseif (!empty($httpXImpersonate))
{
return $httpXImpersonate;
}
}

/**
* Find if the user is trying impersonate other user
*
* @param int $tokenUserId The userid for which token hash is validated
*
* @return int|boolean User id or Email id or null
*
* @since __DEPLOY_VERSION__
*/
public static function getUserIdToImpersonate($tokenUserId)
{
// Lets find out if user trying to impersonate other user
$userToImpersonate = self::getImpersonateHeader();

// If other is to be impersonated
if (!$userToImpersonate)
{
return false;
}

// Get user from tokenUserId
$user = JFactory::getUser($tokenUserId);
$isSuperAdmin = $user->authorise('core.admin');

// If this user is not super admin user, return false
if (!$isSuperAdmin)
{
ApiError::raiseError(403, "Not authorised to use Impersonation", 'APIUnauthorisedException');
}

$searchFor = '';
$searchForValue = '';

if (preg_match('/email:(\S+)/', $userToImpersonate, $matches))
{
$searchFor = 'email';
$searchForValue = $matches[1];
}
elseif (preg_match('/username:(\S+)/', $userToImpersonate, $matches))
{
$searchFor = 'username';
$searchForValue = $matches[1];
}
elseif (is_numeric($userToImpersonate))
{
$userId = $userToImpersonate;
}
else
{
ApiError::raiseError("400", JText::_('COM_API_INVALID_USER_TO_IMPERSONATE'), 'APIValidationException');

return false;
}

// If username or emailid exists ?
if ($searchFor)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__users'))
->where($db->quoteName($searchFor) . ' = ' . $db->quote($searchForValue));
$db->setQuery($query);

if ($id = $db->loadResult())
{
return $id;
}
else
{
ApiError::raiseError("400", JText::_('COM_API_INVALID_USER_TO_IMPERSONATE'), 'APIValidationException');

return false;
}
}
// If userid exists ?
elseif ($userId)
{
$table = JUser::getTable();

if ($table->load($userId))
{
return $userId;
}
else
{
ApiError::raiseError("400", JText::_('COM_API_INVALID_USER_TO_IMPERSONATE'), 'APIValidationException');

return false;
}
}
}
}
24 changes: 15 additions & 9 deletions code/site/libraries/authentication/key.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @copyright Copyright (C) 2009-2017 Techjoomla, Tekdi Technologies Pvt. Ltd. All rights reserved.
* @license GNU GPLv2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
* @link http://techjoomla.com
* Work derived from the original RESTful API by Techjoomla (https://github.com/techjoomla/Joomla-REST-API)
* Work derived from the original RESTful API by Techjoomla (https://github.com/techjoomla/Joomla-REST-API)
* and the com_api extension by Brian Edgerton (http://www.edgewebworks.com)
*/

Expand All @@ -18,26 +18,32 @@
*/
class ApiAuthenticationKey extends ApiAuthentication
{
protected $auth_method = null;
protected $auth_method = null;

protected $domain_checking = null;
protected $domain_checking = null;

/**
* Authenticate the user using the key in the header or request
*
* @return string User id of the user or false
* @return int|boolean User id of the user or false
*/
public function authenticate()
{
$app = JFactory::getApplication();
$query_token = $app->input->get('key', '', 'STRING');
$app = JFactory::getApplication();
$query_token = $app->input->get('key', '', 'STRING');
$header_token = $this->getBearerToken();
$key = $header_token ? $header_token : $query_token;

$token = $this->loadTokenByHash($key);
$key = $header_token ? $header_token : $query_token;
$token = $this->loadTokenByHash($key);

if (isset($token->state) && $token->state == 1)
{
$userId = parent::getUserIdToImpersonate($token->userid);

if ($userId)
{
return $userId;
}

return $token->userid;
}

Expand Down

0 comments on commit b407202

Please sign in to comment.