mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-05-12 05:22:35 +09:00
Move checkSSO() from Context class to Session class
This commit is contained in:
parent
483ac84796
commit
af41f36bf7
3 changed files with 106 additions and 92 deletions
|
|
@ -670,97 +670,7 @@ class Context
|
||||||
*/
|
*/
|
||||||
public function checkSSO()
|
public function checkSSO()
|
||||||
{
|
{
|
||||||
// pass if it's not GET request or XE is not yet installed
|
return !Rhymix\Framework\Session::checkSSO();
|
||||||
if(!config('use_sso') || Rhymix\Framework\UA::isRobot())
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
$checkActList = array('rss' => 1, 'atom' => 1);
|
|
||||||
if(self::getRequestMethod() != 'GET' || !self::isInstalled() || isset($checkActList[self::get('act')]))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass if default URL is not set
|
|
||||||
$default_url = trim($this->db_info->default_url);
|
|
||||||
if(!$default_url)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(substr_compare($default_url, '/', -1) !== 0)
|
|
||||||
{
|
|
||||||
$default_url .= '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current site information (only the base URL, not the full URL)
|
|
||||||
$current_site = self::getRequestUri();
|
|
||||||
|
|
||||||
// Step 1: if the current site is not the default site, send SSO validation request to the default site
|
|
||||||
if($default_url !== $current_site && !self::get('sso_response') && $_COOKIE['sso'] !== md5($current_site))
|
|
||||||
{
|
|
||||||
// Set sso cookie to prevent multiple simultaneous SSO validation requests
|
|
||||||
setcookie('sso', md5($current_site), 0, '/');
|
|
||||||
|
|
||||||
// Redirect to the default site
|
|
||||||
$sso_request = Rhymix\Framework\Security::encrypt(Rhymix\Framework\URL::getCurrentURL());
|
|
||||||
$redirect_url = $default_url . '?sso_request=' . urlencode($sso_request);
|
|
||||||
header('Location:' . $redirect_url);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: receive and process SSO validation request at the default site
|
|
||||||
if($default_url === $current_site && self::get('sso_request'))
|
|
||||||
{
|
|
||||||
// Get the URL of the origin site
|
|
||||||
$sso_request = Rhymix\Framework\Security::decrypt(self::get('sso_request'));
|
|
||||||
if (!$sso_request || !preg_match('!^https?://!', $sso_request))
|
|
||||||
{
|
|
||||||
self::displayErrorPage('SSO Error', 'Invalid SSO Request', 400);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the origin site is a valid site in this XE installation (to prevent open redirect vuln)
|
|
||||||
if(!getModel('module')->getSiteInfoByDomain(rtrim($url, '/'))->site_srl)
|
|
||||||
{
|
|
||||||
self::displayErrorPage('SSO Error', 'Invalid SSO Request', 400);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect back to the origin site
|
|
||||||
$sso_response = Rhymix\Framework\Security::encrypt(session_id());
|
|
||||||
header('Location: ' . Rhymix\Framework\URL::modifyURL($sso_request, array('sso_response' => $sso_response)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: back at the origin site, set session ID to be the same as the default site
|
|
||||||
if($default_url !== $current_site && self::get('sso_response'))
|
|
||||||
{
|
|
||||||
// Check SSO response
|
|
||||||
$sso_response = Rhymix\Framework\Security::decrypt(self::get('sso_response'));
|
|
||||||
if ($sso_response === false)
|
|
||||||
{
|
|
||||||
self::displayErrorPage('SSO Error', 'Invalid SSO Response', 400);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the response was given by the default site (to prevent session fixation CSRF)
|
|
||||||
if(isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $default_url) !== 0)
|
|
||||||
{
|
|
||||||
self::displayErrorPage('SSO Error', 'Invalid SSO Response', 400);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set session ID
|
|
||||||
setcookie(session_name(), $sso_response);
|
|
||||||
|
|
||||||
// Finally, redirect to the originally requested URL
|
|
||||||
header('Location: ' . Rhymix\Framework\URL::getCurrentURL(array('sso_response' => null)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If none of the conditions above apply, proceed normally
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,11 @@ class Session
|
||||||
// Validate the HTTP key.
|
// Validate the HTTP key.
|
||||||
if (isset($_SESSION['RHYMIX']) && $_SESSION['RHYMIX'])
|
if (isset($_SESSION['RHYMIX']) && $_SESSION['RHYMIX'])
|
||||||
{
|
{
|
||||||
if ($_SESSION['RHYMIX']['keys'][$domain]['key1'] === $key1 && $key1 !== null)
|
if (!isset($_SESSION['RHYMIX']['keys'][$domain]) && config('use_sso'))
|
||||||
|
{
|
||||||
|
$must_refresh = true;
|
||||||
|
}
|
||||||
|
elseif ($_SESSION['RHYMIX']['keys'][$domain]['key1'] === $key1 && $key1 !== null)
|
||||||
{
|
{
|
||||||
// OK
|
// OK
|
||||||
}
|
}
|
||||||
|
|
@ -220,6 +224,95 @@ class Session
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this session needs to be shared with another site with SSO.
|
||||||
|
*
|
||||||
|
* This method uses more or less the same logic as XE's SSO mechanism.
|
||||||
|
* It may need to be changed to a more secure mechanism later.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function checkSSO()
|
||||||
|
{
|
||||||
|
// Abort if SSO is disabled, the visitor is a robot, or this is not a typical GET request.
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET' || !config('use_sso') || UA::isRobot() || in_array(\Context::get('act'), array('rss', 'atom')))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort of the default URL is not set.
|
||||||
|
$default_url = \Context::getDefaultUrl();
|
||||||
|
if (!$default_url)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current site information.
|
||||||
|
$current_url = URL::getCurrentURL();
|
||||||
|
$current_host = parse_url($current_url, \PHP_URL_HOST);
|
||||||
|
$default_host = parse_url($default_url, \PHP_URL_HOST);
|
||||||
|
|
||||||
|
// Step 1: if the current site is not the default site, send SSO validation request to the default site.
|
||||||
|
if($default_host !== $current_host && !\Context::get('sso_response') && $_COOKIE['sso'] !== md5($current_host))
|
||||||
|
{
|
||||||
|
// Set sso cookie to prevent multiple simultaneous SSO validation requests.
|
||||||
|
setcookie('sso', md5($current_host), 0, '/');
|
||||||
|
|
||||||
|
// Redirect to the default site.
|
||||||
|
$sso_request = Security::encrypt($current_url);
|
||||||
|
header('Location:' . URL::modifyURL($default_url, array('sso_request' => $sso_request)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: receive and process SSO validation request at the default site.
|
||||||
|
if($default_host === $current_host && \Context::get('sso_request'))
|
||||||
|
{
|
||||||
|
// Get the URL of the origin site
|
||||||
|
$sso_request = Security::decrypt(\Context::get('sso_request'));
|
||||||
|
if (!$sso_request || !preg_match('!^https?://!', $sso_request))
|
||||||
|
{
|
||||||
|
\Context::displayErrorPage('SSO Error', 'Invalid SSO Request', 400);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect back to the origin site.
|
||||||
|
$sso_response = Security::encrypt(session_id());
|
||||||
|
header('Location: ' . URL::modifyURL($sso_request, array('sso_response' => $sso_response)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: back at the origin site, set session ID to be the same as the default site.
|
||||||
|
if($default_host !== $current_host && \Context::get('sso_response'))
|
||||||
|
{
|
||||||
|
// Check SSO response
|
||||||
|
$sso_response = Security::decrypt(\Context::get('sso_response'));
|
||||||
|
if ($sso_response === false)
|
||||||
|
{
|
||||||
|
\Context::displayErrorPage('SSO Error', 'Invalid SSO Response', 400);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the response was given by the default site (to prevent session fixation CSRF).
|
||||||
|
if(isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $default_url) !== 0)
|
||||||
|
{
|
||||||
|
\Context::displayErrorPage('SSO Error', 'Invalid SSO Response', 400);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set session ID.
|
||||||
|
self::close();
|
||||||
|
session_id($sso_response);
|
||||||
|
self::start();
|
||||||
|
|
||||||
|
// Finally, redirect to the originally requested URL.
|
||||||
|
header('Location: ' . URL::getCurrentURL(array('sso_response' => null)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If none of the conditions above apply, proceed normally.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the data structure for a new Rhymix session.
|
* Create the data structure for a new Rhymix session.
|
||||||
*
|
*
|
||||||
|
|
@ -261,6 +354,12 @@ class Session
|
||||||
// Get session parameters.
|
// Get session parameters.
|
||||||
list($lifetime, $refresh_interval, $domain, $path) = self::_getParams();
|
list($lifetime, $refresh_interval, $domain, $path) = self::_getParams();
|
||||||
|
|
||||||
|
// Set the domain initialization timestamp.
|
||||||
|
if (!isset($_SESSION['RHYMIX']['keys'][$domain]['started']))
|
||||||
|
{
|
||||||
|
$_SESSION['RHYMIX']['keys'][$domain]['started'] = time();
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the trusted information.
|
// Reset the trusted information.
|
||||||
if (!isset($_SESSION['RHYMIX']['keys'][$domain]['trusted']))
|
if (!isset($_SESSION['RHYMIX']['keys'][$domain]['trusted']))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ class SessionTest extends \Codeception\TestCase\Test
|
||||||
$this->assertTrue(Rhymix\Framework\Session::isStarted());
|
$this->assertTrue(Rhymix\Framework\Session::isStarted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCheckSSO()
|
||||||
|
{
|
||||||
|
$this->assertFalse(Rhymix\Framework\Session::checkSSO());
|
||||||
|
}
|
||||||
|
|
||||||
public function testRefresh()
|
public function testRefresh()
|
||||||
{
|
{
|
||||||
Rhymix\Framework\Session::start();
|
Rhymix\Framework\Session::start();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue