diff --git a/config-templates/module_perun.php b/config-templates/module_perun.php index 3aea2498fb61ef5b071d2a4dad9b170b321215aa..9845441aff55419d1e5b49b367b52b0bd0cc47e6 100644 --- a/config-templates/module_perun.php +++ b/config-templates/module_perun.php @@ -190,10 +190,10 @@ $config = [ 'wayf_config' => [ /** - * specify if disco module should filter out IdPs which are not whitelisted neither commited to CoCo or RaS. + * specify if disco module should filter out IdPs which are not whitelisted neither committed to CoCo or RaS. * default is false. */ - 'disable_white_listing', + 'disable_white_listing' => false, /** * Specify translate module */ @@ -202,7 +202,7 @@ $config = [ * Specify prefix for filtering AuthnContextClassRef * All AuthnContextClassRef values starts with this prefix will be removed before the request will be send to IdP */ - 'remove_authn_context_class_ref_prefix' => 'urn:cesnet:proxyidp:', + 'remove_authn_context_class_ref_prefixes' => ['urn:cesnet:proxyidp:'], /** * Add insitution configuration. The block has to specify email and url */ @@ -212,7 +212,7 @@ $config = [ ], /** * Warning configuration - * The configuration can be loaded from file, url or directly formt his config. All possibilities has to follow + * The configuration can be loaded from file, url or directly from this config. All possibilities has to follow * the structure under the "config" key. */ 'warning_config' => [ diff --git a/lib/Disco.php b/lib/Disco.php index 1845df3ab37a09af992c3f29ae78e96df83d7877..cdcdceb3fd625e6ea379c3ab7d93dcc666496ab7 100644 --- a/lib/Disco.php +++ b/lib/Disco.php @@ -34,6 +34,9 @@ class Disco extends PowerIdPDisco public const WAYF = 'wayf_config'; # CONFIGURATION ENTRIES public const BOXED = 'boxed'; + public const TRANSLATE_MODULE = 'translate_module'; + public const REMOVE_AUTHN_CONTEXT_CLASS_PREFIXES = 'remove_authn_context_class_ref_prefixes'; + public const DISABLE_WHITELISTING = 'disable_whitelisting'; # CONFIGURATION ENTRIES IDP BLOCKS public const IDP_BLOCKS = 'idp_blocks_config'; public const IDP_BLOCK_TYPE = 'type'; @@ -50,9 +53,6 @@ class Disco extends PowerIdPDisco public const ADD_INSTITUTION = 'add_institution_config'; public const ADD_INSTITUTION_URL = 'url'; public const ADD_INSTITUTION_EMAIL = 'email'; - public const TRANSLATE_MODULE = 'translate_module'; - public const REMOVE_AUTHN_CONTEXT_CLASS_PREFIX = 'remove_authn_context_class_ref_prefix'; - public const DISABLE_WHITELISTING = 'disable_whitelisting'; # PARAMS AND DATA KEYS public const ENTITY_ID = "entityID"; @@ -84,12 +84,25 @@ class Disco extends PowerIdPDisco public const SAML_SP_SSO = 'saml:sp:sso'; private $originalsp; - private array $authnContextClassRef = []; + private array $originalAuthnContextClassRef = []; + private $wayfConfiguration; + private $perunModuleConfiguration; + + private $proxyIdpEntityId; public function __construct( array $metadataSets, $instance ) { + //LOAD CONFIG FOR MODULE PERUN, WHICH CONTAINS WAYF CONFIGURATION + try { + $this->perunModuleConfiguration = Configuration::getConfig(Disco::CONFIG_FILE_NAME); + $this->wayfConfiguration = $this->perunModuleConfiguration->getConfigItem(self::WAYF); + } catch (\Exception $ex) { + Logger::error("perun:disco-tpl: missing or invalid '" . self::CONFIG_FILE_NAME . "' config file"); + throw $ex; + } + if (!array_key_exists(self::RETURN, $_GET)) { throw new \Exception('Missing parameter: ' . self::RETURN); } else { @@ -104,13 +117,13 @@ class Disco extends PowerIdPDisco if ($state !== null) { if (isset($state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::AUTHN_CONTEXT_CLASS_REF])) { - $this->authnContextClassRef = $state[self::SAML_REQUESTED_AUTHN_CONTEXT] + $this->originalAuthnContextClassRef = $state[self::SAML_REQUESTED_AUTHN_CONTEXT] [self::AUTHN_CONTEXT_CLASS_REF]; - $this->removeAuthContextClassRefWithPrefix($state); + $this->removeAuthContextClassRefWithPrefixes($state); + if (isset($state['IdPMetadata']['entityid'])) { + $this->proxyIdpEntityId = $state['IdPMetadata']['entityid']; + } } - - $id = State::saveState($state, self::SAML_SP_SSO); - $e = explode("=", $returnURL)[0]; $newReturnURL = $e . "=" . urlencode($id); $_GET[self::RETURN] = $newReturnURL; @@ -143,9 +156,6 @@ class Disco extends PowerIdPDisco } else { $idpList = $this->filterList($idpList); } - $preferredIdP = $this->getRecommendedIdP(); - $preferredIdP = array_key_exists($preferredIdP, $idpList) - ? $preferredIdP : null; if (sizeof($idpList) === 1) { $idp = array_keys($idpList)[0]; @@ -160,15 +170,21 @@ class Disco extends PowerIdPDisco HTTP::redirectTrustedURL($url); } + $preferredIdP = $this->getRecommendedIdP(); + $preferredIdP = array_key_exists($preferredIdP, $idpList) ? $preferredIdP : null; + // IF IS SET AUTHN CONTEXT CLASS REF, REDIRECT USER TO THE IDP - if (isset($this->authnContextClassRef)) { - if ($this->authnContextClassRef !== null) { + if (isset($this->originalAuthnContextClassRef)) { + if ($this->originalAuthnContextClassRef !== null) { # Check authnContextClassRef and select IdP directly if the correct value is set - foreach ($this->authnContextClassRef as $value) { + foreach ($this->originalAuthnContextClassRef as $value) { // VERIFY THE PREFIX IS CORRECT AND WE CAN PERFORM THE REDIRECT $acrStartSubstr = substr($value, 0, strlen(Disco::URN_CESNET_PROXYIDP_IDPENTITYID)); if ($acrStartSubstr === Disco::URN_CESNET_PROXYIDP_IDPENTITYID) { $idpEntityId = substr($value, strlen(Disco::URN_CESNET_PROXYIDP_IDPENTITYID), strlen($value)); + if ($idpEntityId === $this->proxyIdpEntityId) { + continue; + } Logger::info('Redirecting to ' . $idpEntityId); $url = Disco::buildContinueUrl( $this->spEntityId, @@ -182,15 +198,6 @@ class Disco extends PowerIdPDisco } } - //LOAD CONFIG FOR MODULE PERUN, WHICH CONTAINS WAYF CONFIGURATION - $perunModuleConfig = null; - try { - $perunModuleConfig = Configuration::getConfig(Disco::CONFIG_FILE_NAME); - } catch (\Exception $ex) { - Logger::error("perun:disco-tpl: missing or invalid '" . self::CONFIG_FILE_NAME . "' config file"); - throw $ex; - } - $warningAttributes = null; try { $warningInstance = WarningConfiguration::getInstance(); @@ -206,9 +213,9 @@ class Disco extends PowerIdPDisco $t->data[self::ENTITY_ID] = $this->spEntityId; $t->data[self::RETURN] = $this->returnURL; $t->data[self::RETURN_ID_PARAM] = $this->returnIdParam; - $t->data[self::AUTHN_CONTEXT_CLASS_REF] = $this->authnContextClassRef; + $t->data[self::AUTHN_CONTEXT_CLASS_REF] = $this->originalAuthnContextClassRef; $t->data[self::WARNING_ATTRIBUTES] = $warningAttributes; - $t->data[self::WAYF] = $perunModuleConfig->getConfigItem(self::WAYF); + $t->data[self::WAYF] = $this->wayfConfiguration; $t->show(); } @@ -221,8 +228,7 @@ class Disco extends PowerIdPDisco */ protected function filterList($list): array { - $conf = Configuration::getConfig(self::CONFIG_FILE_NAME); - $disableWhitelisting = $conf->getBoolean(self::DISABLE_WHITELISTING, false); + $disableWhitelisting = $this->wayfConfiguration->getBoolean(self::DISABLE_WHITELISTING, false); if (!isset($this->originalsp[Disco::METADATA_DO_NOT_FILTER_IDPS]) || !$this->originalsp[Disco::METADATA_DO_NOT_FILTER_IDPS] @@ -441,24 +447,24 @@ class Disco extends PowerIdPDisco * @param $state * @throws \Exception */ - public function removeAuthContextClassRefWithPrefix(&$state) + public function removeAuthContextClassRefWithPrefixes(&$state) { - $conf = Configuration::getConfig(self::CONFIG_FILE_NAME); - $prefix = $conf->getString(self::REMOVE_AUTHN_CONTEXT_CLASS_PREFIX, null); + $prefixes = $this->wayfConfiguration->getArray(self::REMOVE_AUTHN_CONTEXT_CLASS_PREFIXES, []); - if ($prefix === null) { + if (empty($prefixes)) { return; } unset($state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF]); - $array = []; - foreach ($this->authnContextClassRef as $value) { - if (!(substr($value, 0, strlen($prefix)) === $prefix)) { - array_push($array, $value); + $filteredAcrs = []; + foreach ($this->originalAuthnContextClassRef as $acr) { + foreach ($prefixes as $prefix) { + if (!(substr($acr, 0, strlen($prefix)) === $prefix)) { + array_push($filteredAcrs, $acr); + } } } - if (!empty($array)) { - $state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF] - = $array; + if (!empty($filteredAcrs)) { + $state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF] = $filteredAcrs; } } diff --git a/themes/perun/perun/disco-tpl.php b/themes/perun/perun/disco-tpl.php index d40eebeb91fc15dbce63651223674dcadea13761..c07ce492a692a3c11e287531521d9831c2f1fb4d 100644 --- a/themes/perun/perun/disco-tpl.php +++ b/themes/perun/perun/disco-tpl.php @@ -21,27 +21,24 @@ $this->data['head'] = '<link rel="stylesheet" media="screen" type="text/css" hre $this->data['head'] .= '<link rel="stylesheet" media="screen" type="text/css" href="' . Module::getModuleUrl('perun/res/css/disco.css') . '" />'; -$authContextClassRef = null; -$idpEntityId = null; - $wayfConfig = $this->data[Disco::WAYF]; $translateModule = $wayfConfig->getString(Disco::TRANSLATE_MODULE, 'disco'); - $addInstitutionConfig = $wayfConfig->getConfigItem(Disco::ADD_INSTITUTION, null); $warningAttributes = $this->data[Disco::WARNING_ATTRIBUTES]; -$this->includeInlineTranslation('{perun:disco:warning_title}', $warningAttributes->getTitle()); -$this->includeInlineTranslation('{perun:disco:warning_text}', $warningAttributes->getText()); - -// IF WARNING ERROR IS ENABLED, DISPLAY IT AND STOP THE USER -if ($warningAttributes->isEnabled() && $warningAttributes->getType() === WarningConfiguration::WARNING_TYPE_ERROR) { - $this->data['header'] = $this->t('{perun:disco:warning}'); - $this->includeAtTemplateBase('includes/header.php'); - echo Disco::showWarning($this, $warningAttributes); - $this->includeAtTemplateBase('includes/footer.php'); - echo Disco::getScripts($wayfConfig->getBoolean(Disco::BOXED, false)) . PHP_EOL; - exit; +if ($warningAttributes !== null) { + $this->includeInlineTranslation('{perun:disco:warning_title}', $warningAttributes->getTitle()); + $this->includeInlineTranslation('{perun:disco:warning_text}', $warningAttributes->getText()); + // IF WARNING ERROR IS ENABLED, DISPLAY IT AND STOP THE USER + if ($warningAttributes->isEnabled() && $warningAttributes->getType() === WarningConfiguration::WARNING_TYPE_ERROR) { + $this->data['header'] = $this->t('{perun:disco:warning}'); + $this->includeAtTemplateBase('includes/header.php'); + echo Disco::showWarning($this, $warningAttributes); + $this->includeAtTemplateBase('includes/footer.php'); + echo Disco::getScripts($wayfConfig->getBoolean(Disco::BOXED, false)) . PHP_EOL; + exit; + } } // START DISPLAYING REGULAR WAYF (for users or add-institution) @@ -56,7 +53,7 @@ if ($this->isAddInstitutionApp()) { $this->includeAtTemplateBase('includes/header.php'); # IF WE HAVE A WARNING, DISPLAY IT TO THE USER -if ($warningAttributes->isEnabled()) { +if ($warningAttributes !== null && $warningAttributes->isEnabled()) { echo Disco::showWarning($this, $warningAttributes); } ###