diff --git a/config-templates/config.php b/config-templates/config.php index 812e93985b4a04f4de85bb778fe4b789e539ba9f..386d58f6103208056bc6915f1baa4b0a88add1dd 100644 --- a/config-templates/config.php +++ b/config-templates/config.php @@ -172,6 +172,16 @@ $config = array ( 'default-saml20-idp' => 'https://openidp.feide.no', 'default-shib13-idp' => NULL, 'default-wsfed-idp' => 'urn:federation:pingfederate:localhost', + + /* + * Default IdP discovery service urls. + * This option sets the default IdP discovery service URLs for the SPs in this installation. These + * URLs can be overridden on a per SP basis by setting this option in the metadata for the SP. + * + * By default simpleSAMLphp will use its builtin IdP discovery service. + */ + 'idpdisco.url.shib13' => NULL, + 'idpdisco.url.saml2' => NULL, /* * IdP Discovery service look configuration. diff --git a/docs/source/simplesamlphp-sp.xml b/docs/source/simplesamlphp-sp.xml index 51d272805981951d039568bb7e2efb8b1c1f36ec..bfb6d04cab303940c86a0c93e90651937f93582b 100644 --- a/docs/source/simplesamlphp-sp.xml +++ b/docs/source/simplesamlphp-sp.xml @@ -286,6 +286,19 @@ PHP page.</para> </glossdef> </glossentry> + + <glossentry> + <glossterm>idpdisco.url</glossterm> + + <glossdef> + <para>Set which IdP discovery service this SP should use. If + this is unset, the IdP discovery service specified in the global + option <literal>idpdisco.url.saml2</literal> in + <filename>config/config.php</filename> will be used. If that one + is also unset, the builtin default discovery service will be + used.</para> + </glossdef> + </glossentry> </glosslist> </section> @@ -704,6 +717,19 @@ PHP page.</para> </glossdef> </glossentry> + + <glossentry> + <glossterm>idpdisco.url</glossterm> + + <glossdef> + <para>Set which IdP discovery service this SP should use. If + this is unset, the IdP discovery service specified in the global + option <literal>idpdisco.url.shib13</literal> in + <filename>config/config.php</filename> will be used. If that one + is also unset, the builtin default discovery service will be + used.</para> + </glossdef> + </glossentry> </glosslist> </section> </section> diff --git a/www/admin/metadata.php b/www/admin/metadata.php index 610d6f1e67193f8588e1f91beca8d87ebf89150a..298496dc1524d33fd234fd0dfc46645f48ec4304 100644 --- a/www/admin/metadata.php +++ b/www/admin/metadata.php @@ -29,7 +29,7 @@ try { foreach ($metalist AS $entityid => $mentry) { $results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry, array('entityid', 'host'), - array('request.signing','certificate','privatekey', 'privatekey_pass', 'NameIDFormat', 'ForceAuthn', 'AuthnContextClassRef', 'SPNameQualifier', 'attributemap', 'attributealter', 'attributes', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate') + array('request.signing','certificate','privatekey', 'privatekey_pass', 'NameIDFormat', 'ForceAuthn', 'AuthnContextClassRef', 'SPNameQualifier', 'attributemap', 'attributealter', 'attributes', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate', 'idpdisco.url') ); } $et->data['metadata.saml20-sp-hosted'] = $results; @@ -79,7 +79,7 @@ try { foreach ($metalist AS $entityid => $mentry) { $results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry, array('entityid', 'host'), - array('NameIDFormat', 'ForceAuthn', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate') + array('NameIDFormat', 'ForceAuthn', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate', 'idpdisco.url') ); } $et->data['metadata.shib13-sp-hosted'] = $results; diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php index d2de59f323dce845a66b012664350d806f787d21..1e0a77f5af5a455327ca531ad129be4d71d200b6 100644 --- a/www/saml2/sp/initSSO.php +++ b/www/saml2/sp/initSSO.php @@ -29,6 +29,11 @@ try { $idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-saml20-idp') ; $spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID(); + if($idpentityid === NULL) { + /* We are going to need the SP metadata to determine which IdP discovery service we should use. */ + $spmetadata = $metadata->getMetaData($spentityid); + } + } catch (Exception $exception) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); } @@ -41,7 +46,18 @@ if ($idpentityid == null) { SimpleSAML_Logger::info('SAML2.0 - SP.initSSO: No chosen or default IdP, go to SAML2disco'); - SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'saml2/sp/idpdisco.php', array( + /* Which IdP discovery service should we use? Can be set in SP metadata or in global configuration. + * Falling back to builtin discovery service. + */ + if(array_key_exists('idpdisco.url', $spmetadata)) { + $discourl = $spmetadata['idpdisco.url']; + } elseif($config->getValue('idpdisco.url.saml2', NULL) !== NULL) { + $discourl = $config->getValue('idpdisco.url.saml2', NULL); + } else { + $discourl = '/' . $config->getBaseURL() . 'saml2/sp/idpdisco.php'; + } + + SimpleSAML_Utilities::redirect($discourl, array( 'entityID' => $spentityid, 'return' => SimpleSAML_Utilities::selfURL(), 'returnIDParam' => 'idpentityid') diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php index 6cb61bc05ae38a245a5d1d76ff51fc9383f847bc..00bc56846a19bf905874170f7b16c312f5187388 100644 --- a/www/shib13/sp/initSSO.php +++ b/www/shib13/sp/initSSO.php @@ -29,6 +29,12 @@ try { $idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-shib13-idp') ; $spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID('shib13-sp-hosted'); + if($idpentityid === NULL) { + /* We are going to need the SP metadata to determine which IdP discovery service we should use. */ + $spmetadata = $metadata->getMetaDataCurrent('shib13-sp-hosted'); + } + + } catch (Exception $exception) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); } @@ -40,12 +46,23 @@ if (!isset($session) || !$session->isValid('shib13') ) { if ($idpentityid == null) { SimpleSAML_Logger::info('Shib1.3 - SP.initSSO: No chosen or default IdP, go to Shib13disco'); - - $returnURL = urlencode(SimpleSAML_Utilities::selfURL()); - $discservice = '/' . $config->getBaseURL() . 'shib13/sp/idpdisco.php?entityID=' . $spentityid . - '&return=' . $returnURL . '&returnIDParam=idpentityid'; - SimpleSAML_Utilities::redirect($discservice); - + + /* Which IdP discovery service should we use? Can be set in SP metadata or in global configuration. + * Falling back to builtin discovery service. + */ + if(array_key_exists('idpdisco.url', $spmetadata)) { + $discservice = $spmetadata['idpdisco.url']; + } elseif($config->getValue('idpdisco.url.shib13', NULL) !== NULL) { + $discservice = $config->getValue('idpdisco.url.shib13', NULL); + } else { + $discservice = '/' . $config->getBaseURL() . 'shib13/sp/idpdisco.php'; + } + + SimpleSAML_Utilities::redirect($discservice, array( + 'entityID' => $spentityid, + 'return' => SimpleSAML_Utilities::selfURL(), + 'returnIDParam' => 'idpentityid', + )); }