402 lines
13 KiB
PHP
Executable File
402 lines
13 KiB
PHP
Executable File
<?php
|
|
|
|
namespace SimpleSAML\Auth;
|
|
|
|
use \SimpleSAML_Auth_Source as Source;
|
|
use \SimpleSAML_Auth_State as State;
|
|
use \SimpleSAML_Configuration as Configuration;
|
|
use \SimpleSAML_Error_AuthSource as AuthSourceError;
|
|
use \SimpleSAML\Module;
|
|
use \SimpleSAML_Session as Session;
|
|
use \SimpleSAML\Utils\HTTP;
|
|
|
|
/**
|
|
* Helper class for simple authentication applications.
|
|
*
|
|
* @package SimpleSAMLphp
|
|
*/
|
|
class Simple
|
|
{
|
|
|
|
/**
|
|
* The id of the authentication source we are accessing.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $authSource;
|
|
|
|
/**
|
|
* @var \SimpleSAML_Configuration|null
|
|
*/
|
|
protected $app_config;
|
|
|
|
/**
|
|
* Create an instance with the specified authsource.
|
|
*
|
|
* @param string $authSource The id of the authentication source.
|
|
*/
|
|
public function __construct($authSource)
|
|
{
|
|
assert(is_string($authSource));
|
|
|
|
$this->authSource = $authSource;
|
|
$this->app_config = Configuration::getInstance()->getConfigItem('application', null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve the implementing authentication source.
|
|
*
|
|
* @return \SimpleSAML_Auth_Source The authentication source.
|
|
*
|
|
* @throws \SimpleSAML_Error_AuthSource If the requested auth source is unknown.
|
|
*/
|
|
public function getAuthSource()
|
|
{
|
|
$as = Source::getById($this->authSource);
|
|
if ($as === null) {
|
|
throw new AuthSourceError($this->authSource, 'Unknown authentication source.');
|
|
}
|
|
return $as;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check if the user is authenticated.
|
|
*
|
|
* This function checks if the user is authenticated with the default authentication source selected by the
|
|
* 'default-authsource' option in 'config.php'.
|
|
*
|
|
* @return bool True if the user is authenticated, false if not.
|
|
*/
|
|
public function isAuthenticated()
|
|
{
|
|
$session = Session::getSessionFromRequest();
|
|
|
|
return $session->isValid($this->authSource);
|
|
}
|
|
|
|
|
|
/**
|
|
* Require the user to be authenticated.
|
|
*
|
|
* If the user is authenticated, this function returns immediately.
|
|
*
|
|
* If the user isn't authenticated, this function will authenticate the user with the authentication source, and
|
|
* then return the user to the current page.
|
|
*
|
|
* This function accepts an array $params, which controls some parts of the authentication. See the login()
|
|
* method for a description.
|
|
*
|
|
* @param array $params Various options to the authentication request. See the documentation.
|
|
*/
|
|
public function requireAuth(array $params = array())
|
|
{
|
|
|
|
$session = Session::getSessionFromRequest();
|
|
|
|
if ($session->isValid($this->authSource)) {
|
|
// Already authenticated
|
|
return;
|
|
}
|
|
|
|
$this->login($params);
|
|
}
|
|
|
|
|
|
/**
|
|
* Start an authentication process.
|
|
*
|
|
* This function accepts an array $params, which controls some parts of the authentication. The accepted parameters
|
|
* depends on the authentication source being used. Some parameters are generic:
|
|
* - 'ErrorURL': A URL that should receive errors from the authentication.
|
|
* - 'KeepPost': If the current request is a POST request, keep the POST data until after the authentication.
|
|
* - 'ReturnTo': The URL the user should be returned to after authentication.
|
|
* - 'ReturnCallback': The function we should call after the user has finished authentication.
|
|
*
|
|
* Please note: this function never returns.
|
|
*
|
|
* @param array $params Various options to the authentication request.
|
|
*/
|
|
public function login(array $params = array())
|
|
{
|
|
|
|
if (array_key_exists('KeepPost', $params)) {
|
|
$keepPost = (bool) $params['KeepPost'];
|
|
} else {
|
|
$keepPost = true;
|
|
}
|
|
|
|
if (array_key_exists('ReturnTo', $params)) {
|
|
$returnTo = (string) $params['ReturnTo'];
|
|
} else {
|
|
if (array_key_exists('ReturnCallback', $params)) {
|
|
$returnTo = (array) $params['ReturnCallback'];
|
|
} else {
|
|
$returnTo = HTTP::getSelfURL();
|
|
}
|
|
}
|
|
|
|
if (is_string($returnTo) && $keepPost && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$returnTo = HTTP::getPOSTRedirectURL($returnTo, $_POST);
|
|
}
|
|
|
|
if (array_key_exists('ErrorURL', $params)) {
|
|
$errorURL = (string) $params['ErrorURL'];
|
|
} else {
|
|
$errorURL = null;
|
|
}
|
|
|
|
|
|
if (!isset($params[State::RESTART]) && is_string($returnTo)) {
|
|
/*
|
|
* A URL to restart the authentication, in case the user bookmarks
|
|
* something, e.g. the discovery service page.
|
|
*/
|
|
$restartURL = $this->getLoginURL($returnTo);
|
|
$params[State::RESTART] = $restartURL;
|
|
}
|
|
|
|
$as = $this->getAuthSource();
|
|
$as->initLogin($returnTo, $errorURL, $params);
|
|
assert(false);
|
|
}
|
|
|
|
|
|
/**
|
|
* Log the user out.
|
|
*
|
|
* This function logs the user out. It will never return. By default, it will cause a redirect to the current page
|
|
* after logging the user out, but a different URL can be given with the $params parameter.
|
|
*
|
|
* Generic parameters are:
|
|
* - 'ReturnTo': The URL the user should be returned to after logout.
|
|
* - 'ReturnCallback': The function that should be called after logout.
|
|
* - 'ReturnStateParam': The parameter we should return the state in when redirecting.
|
|
* - 'ReturnStateStage': The stage the state array should be saved with.
|
|
*
|
|
* @param string|array|null $params Either the URL the user should be redirected to after logging out, or an array
|
|
* with parameters for the logout. If this parameter is null, we will return to the current page.
|
|
*/
|
|
public function logout($params = null)
|
|
{
|
|
assert(is_array($params) || is_string($params) || $params === null);
|
|
|
|
if ($params === null) {
|
|
$params = HTTP::getSelfURL();
|
|
}
|
|
|
|
if (is_string($params)) {
|
|
$params = array(
|
|
'ReturnTo' => $params,
|
|
);
|
|
}
|
|
|
|
assert(is_array($params));
|
|
assert(isset($params['ReturnTo']) || isset($params['ReturnCallback']));
|
|
|
|
if (isset($params['ReturnStateParam']) || isset($params['ReturnStateStage'])) {
|
|
assert(isset($params['ReturnStateParam'], $params['ReturnStateStage']));
|
|
}
|
|
|
|
$session = Session::getSessionFromRequest();
|
|
if ($session->isValid($this->authSource)) {
|
|
$state = $session->getAuthData($this->authSource, 'LogoutState');
|
|
if ($state !== null) {
|
|
$params = array_merge($state, $params);
|
|
}
|
|
|
|
$session->doLogout($this->authSource);
|
|
|
|
$params['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted');
|
|
|
|
$as = Source::getById($this->authSource);
|
|
if ($as !== null) {
|
|
$as->logout($params);
|
|
}
|
|
}
|
|
|
|
self::logoutCompleted($params);
|
|
}
|
|
|
|
|
|
/**
|
|
* Called when logout operation completes.
|
|
*
|
|
* This function never returns.
|
|
*
|
|
* @param array $state The state after the logout.
|
|
*/
|
|
public static function logoutCompleted($state)
|
|
{
|
|
assert(is_array($state));
|
|
assert(isset($state['ReturnTo']) || isset($state['ReturnCallback']));
|
|
|
|
if (isset($state['ReturnCallback'])) {
|
|
call_user_func($state['ReturnCallback'], $state);
|
|
assert(false);
|
|
} else {
|
|
$params = array();
|
|
if (isset($state['ReturnStateParam']) || isset($state['ReturnStateStage'])) {
|
|
assert(isset($state['ReturnStateParam'], $state['ReturnStateStage']));
|
|
$stateID = State::saveState($state, $state['ReturnStateStage']);
|
|
$params[$state['ReturnStateParam']] = $stateID;
|
|
}
|
|
\SimpleSAML\Utils\HTTP::redirectTrustedURL($state['ReturnTo'], $params);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve attributes of the current user.
|
|
*
|
|
* This function will retrieve the attributes of the current user if the user is authenticated. If the user isn't
|
|
* authenticated, it will return an empty array.
|
|
*
|
|
* @return array The users attributes.
|
|
*/
|
|
public function getAttributes()
|
|
{
|
|
|
|
if (!$this->isAuthenticated()) {
|
|
// Not authenticated
|
|
return array();
|
|
}
|
|
|
|
// Authenticated
|
|
$session = Session::getSessionFromRequest();
|
|
return $session->getAuthData($this->authSource, 'Attributes');
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve authentication data.
|
|
*
|
|
* @param string $name The name of the parameter, e.g. 'Attributes', 'Expire' or 'saml:sp:IdP'.
|
|
*
|
|
* @return mixed|null The value of the parameter, or null if it isn't found or we are unauthenticated.
|
|
*/
|
|
public function getAuthData($name)
|
|
{
|
|
assert(is_string($name));
|
|
|
|
if (!$this->isAuthenticated()) {
|
|
return null;
|
|
}
|
|
|
|
$session = Session::getSessionFromRequest();
|
|
return $session->getAuthData($this->authSource, $name);
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve all authentication data.
|
|
*
|
|
* @return array|null All persistent authentication data, or null if we aren't authenticated.
|
|
*/
|
|
public function getAuthDataArray()
|
|
{
|
|
|
|
if (!$this->isAuthenticated()) {
|
|
return null;
|
|
}
|
|
|
|
$session = Session::getSessionFromRequest();
|
|
return $session->getAuthState($this->authSource);
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve a URL that can be used to log the user in.
|
|
*
|
|
* @param string|null $returnTo The page the user should be returned to afterwards. If this parameter is null, the
|
|
* user will be returned to the current page.
|
|
*
|
|
* @return string A URL which is suitable for use in link-elements.
|
|
*/
|
|
public function getLoginURL($returnTo = null)
|
|
{
|
|
assert($returnTo === null || is_string($returnTo));
|
|
|
|
if ($returnTo === null) {
|
|
$returnTo = HTTP::getSelfURL();
|
|
}
|
|
|
|
$login = Module::getModuleURL('core/as_login.php', array(
|
|
'AuthId' => $this->authSource,
|
|
'ReturnTo' => $returnTo,
|
|
));
|
|
|
|
return $login;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve a URL that can be used to log the user out.
|
|
*
|
|
* @param string|null $returnTo The page the user should be returned to afterwards. If this parameter is null, the
|
|
* user will be returned to the current page.
|
|
*
|
|
* @return string A URL which is suitable for use in link-elements.
|
|
*/
|
|
public function getLogoutURL($returnTo = null)
|
|
{
|
|
assert($returnTo === null || is_string($returnTo));
|
|
|
|
if ($returnTo === null) {
|
|
$returnTo = HTTP::getSelfURL();
|
|
}
|
|
|
|
$logout = Module::getModuleURL('core/as_logout.php', array(
|
|
'AuthId' => $this->authSource,
|
|
'ReturnTo' => $returnTo,
|
|
));
|
|
|
|
return $logout;
|
|
}
|
|
|
|
|
|
/**
|
|
* Process a URL and modify it according to the application/baseURL configuration option, if present.
|
|
*
|
|
* @param string|null $url The URL to process, or null if we want to use the current URL. Both partial and full
|
|
* URLs can be used as a parameter. The maximum precedence is given to the application/baseURL configuration option,
|
|
* then the URL specified (if it specifies scheme, host and port) and finally the environment observed in the
|
|
* server.
|
|
*
|
|
* @return string The URL modified according to the precedence rules.
|
|
*/
|
|
protected function getProcessedURL($url = null)
|
|
{
|
|
if ($url === null) {
|
|
$url = HTTP::getSelfURL();
|
|
}
|
|
|
|
$scheme = parse_url($url, PHP_URL_SCHEME);
|
|
$host = parse_url($url, PHP_URL_HOST) ?: HTTP::getSelfHost();
|
|
$port = parse_url($url, PHP_URL_PORT) ?: (
|
|
$scheme ? '' : trim(HTTP::getServerPort(), ':')
|
|
);
|
|
$scheme = $scheme ?: (HTTP::getServerHTTPS() ? 'https' : 'http');
|
|
$path = parse_url($url, PHP_URL_PATH) ?: '/';
|
|
$query = parse_url($url, PHP_URL_QUERY) ?: '';
|
|
$fragment = parse_url($url, PHP_URL_FRAGMENT) ?: '';
|
|
|
|
$port = !empty($port) ? ':'.$port : '';
|
|
if (($scheme === 'http' && $port === ':80') || ($scheme === 'https' && $port === ':443')) {
|
|
$port = '';
|
|
}
|
|
|
|
if (is_null($this->app_config)) {
|
|
// nothing more we can do here
|
|
return $scheme.'://'.$host.$port.$path.($query ? '?'.$query : '').($fragment ? '#'.$fragment : '');
|
|
}
|
|
|
|
$base = trim($this->app_config->getString(
|
|
'baseURL',
|
|
$scheme.'://'.$host.$port
|
|
), '/');
|
|
return $base.$path.($query ? '?'.$query : '').($fragment ? '#'.$fragment : '');
|
|
}
|
|
}
|