An exception will be thrown if this option isn't a boolean, or if this option isn't found, and no default value
is given.
public getBoolean ( string $name, mixed $default = self::REQUIRED_OPTION ) : boolean | mixed | ||
$name | string | The name of the option. |
$default | mixed | A default value which will be returned if the option isn't found. The option will be required if this parameter isn't given. The default value can be any value, including null. |
return | boolean | mixed | The option with the given name, or $default if the option isn't found and $default is specified. |
/** * Constructor * * @param \SimpleSAML_Configuration $configuration Configuration object */ public function __construct(\SimpleSAML_Configuration $configuration) { $this->configuration = $configuration; $this->availableLanguages = $this->configuration->getArray('language.available', array('en')); $this->defaultLanguage = $this->configuration->getString('language.default', 'en'); $this->languageParameterName = $this->configuration->getString('language.parameter.name', 'language'); $this->customFunction = $this->configuration->getArray('language.get_language_function', null); $this->rtlLanguages = $this->configuration->getArray('language.rtl', array()); if (isset($_GET[$this->languageParameterName])) { $this->setLanguage($_GET[$this->languageParameterName], $this->configuration->getBoolean('language.parameter.setcookie', true)); } }
/** * Setup twig. */ private function setupTwig() { $auto_reload = $this->configuration->getBoolean('template.auto_reload', true); $cache = false; if (!$auto_reload) { // Cache only used if auto_reload = false $cache = $this->configuration->getString('template.cache', $this->configuration->resolvePath('cache')); } // set up template paths $loader = $this->setupTwigTemplatepaths(); // abort if twig template does not exist if (!$loader->exists($this->twig_template)) { return false; } // load extra i18n domains if ($this->module) { $this->localization->addModuleDomain($this->module); } $options = array('cache' => $cache, 'auto_reload' => $auto_reload, 'translation_function' => array('\\SimpleSAML\\Locale\\Translate', 'translateSingularNativeGettext'), 'translation_function_plural' => array('\\SimpleSAML\\Locale\\Translate', 'translatePluralNativeGettext')); // set up translation if ($this->localization->i18nBackend === \SimpleSAML\Locale\Localization::GETTEXT_I18N_BACKEND) { $options['translation_function'] = array('\\SimpleSAML\\Locale\\Translate', 'translateSingularGettext'); $options['translation_function_plural'] = array('\\SimpleSAML\\Locale\\Translate', 'translatePluralGettext'); } // TODO: add a branch for the old SimpleSAMLphp backend $twig = new Twig_Environment($loader, $options); $twig->addExtension(new Twig_Extensions_Extension_I18n()); return $twig; }
/** * Check that the user has access to the statistics. * * If the user doesn't have access, send the user to the login page. */ public static function checkAccess(SimpleSAML_Configuration $statconfig) { $protected = $statconfig->getBoolean('protected', FALSE); $authsource = $statconfig->getString('auth', NULL); $allowedusers = $statconfig->getValue('allowedUsers', NULL); $useridattr = $statconfig->getString('useridattr', 'eduPersonPrincipalName'); $acl = $statconfig->getValue('acl', NULL); if ($acl !== NULL && !is_string($acl) && !is_array($acl)) { throw new SimpleSAML_Error_Exception('Invalid value for \'acl\'-option. Should be an array or a string.'); } if (!$protected) { return; } if (SimpleSAML\Utils\Auth::isAdmin()) { // User logged in as admin. OK. SimpleSAML_Logger::debug('Statistics auth - logged in as admin, access granted'); return; } if (!isset($authsource)) { // If authsource is not defined, init admin login. SimpleSAML\Utils\Auth::requireAdmin(); } /* We are using an authsource for login. */ $as = new SimpleSAML_Auth_Simple($authsource); $as->requireAuth(); // User logged in with auth source. SimpleSAML_Logger::debug('Statistics auth - valid login with auth source [' . $authsource . ']'); // Retrieving attributes $attributes = $as->getAttributes(); if (!empty($allowedusers)) { // Check if userid exists if (!isset($attributes[$useridattr][0])) { throw new Exception('User ID is missing'); } // Check if userid is allowed access.. if (in_array($attributes[$useridattr][0], $allowedusers)) { SimpleSAML_Logger::debug('Statistics auth - User granted access by user ID [' . $attributes[$useridattr][0] . ']'); return; } SimpleSAML_Logger::debug('Statistics auth - User denied access by user ID [' . $attributes[$useridattr][0] . ']'); } else { SimpleSAML_Logger::debug('Statistics auth - no allowedUsers list.'); } if (!is_null($acl)) { $acl = new sspmod_core_ACL($acl); if ($acl->allows($attributes)) { SimpleSAML_Logger::debug('Statistics auth - allowed access by ACL.'); return; } SimpleSAML_Logger::debug('Statistics auth - denied access by ACL.'); } else { SimpleSAML_Logger::debug('Statistics auth - no ACL configured.'); } throw new SimpleSAML_Error_Exception('Access denied to the current user.'); }
/** * Determine whether metadata signing is enabled for the given metadata. * * @param SimpleSAML_Configuration $config Our SimpleSAML_Configuration instance. * @param array $entityMetadata The metadata of the entity. * @param string $type A string which describes the type entity this is, e.g. 'SAML 2 IdP' or * 'Shib 1.3 SP'. * * @return boolean True if metadata signing is enabled, false otherwise. * @throws Exception If the value of the 'metadata.sign.enable' option is not a boolean. */ private static function isMetadataSigningEnabled($config, $entityMetadata, $type) { // first check the metadata for the entity if (array_key_exists('metadata.sign.enable', $entityMetadata)) { if (!is_bool($entityMetadata['metadata.sign.enable'])) { throw new Exception('Invalid value for the "metadata.sign.enable" configuration option for' . ' the ' . $type . ' "' . $entityMetadata['entityid'] . '". This option' . ' should be a boolean.'); } return $entityMetadata['metadata.sign.enable']; } $enabled = $config->getBoolean('metadata.sign.enable', false); return $enabled; }
private static function enrichForDecryptionProvider(SimpleSAML_Configuration $configuration, array &$baseConfiguration) { if ($configuration->has('sharedKey')) { $baseConfiguration['sharedKey'] = $configuration->getString('sharedKey', NULL); } if ($configuration->has('new_privatekey')) { $baseConfiguration['privateKeys'][] = new SAML2_Configuration_PrivateKey($configuration->getString('new_privatekey'), SAML2_Configuration_PrivateKey::NAME_NEW, $configuration->getString('new_privatekey_pass', NULL)); } if ($configuration->getBoolean('assertion.encryption', FALSE)) { $baseConfiguration['privateKeys'][] = new SAML2_Configuration_PrivateKey($configuration->getString('privatekey'), SAML2_Configuration_PrivateKey::NAME_DEFAULT, $configuration->getString('privatekey_pass', NULL)); if ($configuration->has('encryption.blacklisted-algorithms')) { $baseConfiguration['blacklistedEncryptionAlgorithms'] = $configuration->get('encryption.blacklisted-algorithms'); } } }
/** * Send an authenticationResponse using HTTP-POST. * * @param string $response The response which should be sent. * @param SimpleSAML_Configuration $idpmd The metadata of the IdP which is sending the response. * @param SimpleSAML_Configuration $spmd The metadata of the SP which is receiving the response. * @param string|null $relayState The relaystate for the SP. * @param string $shire The shire which should receive the response. */ public function sendResponse($response, SimpleSAML_Configuration $idpmd, SimpleSAML_Configuration $spmd, $relayState, $shire) { \SimpleSAML\Utils\XML::checkSAMLMessage($response, 'saml11'); $privatekey = SimpleSAML\Utils\Crypto::loadPrivateKey($idpmd, true); $publickey = SimpleSAML\Utils\Crypto::loadPublicKey($idpmd, true); $responsedom = new DOMDocument(); $responsedom->loadXML(str_replace("\r", "", $response)); $responseroot = $responsedom->getElementsByTagName('Response')->item(0); $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); /* Determine what we should sign - either the Response element or the Assertion. The default is to sign the * Assertion, but that can be overridden by the 'signresponse' option in the SP metadata or * 'saml20.signresponse' in the global configuration. * * TODO: neither 'signresponse' nor 'shib13.signresponse' are valid options any longer. Remove! */ if ($spmd->hasValue('signresponse')) { $signResponse = $spmd->getBoolean('signresponse'); } else { $signResponse = $this->configuration->getBoolean('shib13.signresponse', true); } // check if we have an assertion to sign. Force to sign the response if not if ($firstassertionroot === null) { $signResponse = true; } $signer = new SimpleSAML_XML_Signer(array('privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => $signResponse ? 'ResponseID' : 'AssertionID')); if ($idpmd->hasValue('certificatechain')) { $signer->addCertificate($idpmd->getString('certificatechain')); } if ($signResponse) { // sign the response - this must be done after encrypting the assertion // we insert the signature before the saml2p:Status element $statusElements = SimpleSAML\Utils\XML::getDOMChildren($responseroot, 'Status', '@saml1p'); assert('count($statusElements) === 1'); $signer->sign($responseroot, $responseroot, $statusElements[0]); } else { /* Sign the assertion */ $signer->sign($firstassertionroot, $firstassertionroot); } $response = $responsedom->saveXML(); \SimpleSAML\Utils\XML::debugSAMLMessage($response, 'out'); \SimpleSAML\Utils\HTTP::submitPOSTData($shire, array('TARGET' => $relayState, 'SAMLResponse' => base64_encode($response))); }
/** * Handles a request to this discovery service. * * The IdP disco parameters should be set before calling this function. */ public function handleRequest() { $this->start(); // no choice made. Show discovery service page $idpList = $this->getIdPList(); $idpList = $this->filterList($idpList); $preferredIdP = $this->getRecommendedIdP(); $idpintersection = array_intersect(array_keys($idpList), $this->getScopedIDPList()); if (sizeof($idpintersection) > 0) { $idpList = array_intersect_key($idpList, array_fill_keys($idpintersection, null)); } $idpintersection = array_values($idpintersection); if (sizeof($idpintersection) == 1) { $this->log('Choice made [' . $idpintersection[0] . '] (Redirecting the user back. returnIDParam=' . $this->returnIdParam . ')'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($this->returnURL, array($this->returnIdParam => $idpintersection[0])); } /* * Make use of an XHTML template to present the select IdP choice to the user. Currently the supported options * is either a drop down menu or a list view. */ switch ($this->config->getString('idpdisco.layout', 'links')) { case 'dropdown': $templateFile = 'selectidp-dropdown.php'; break; case 'links': $templateFile = 'selectidp-links.php'; break; default: throw new Exception('Invalid value for the \'idpdisco.layout\' option.'); } $t = new SimpleSAML_XHTML_Template($this->config, $templateFile, 'disco'); $t->data['idplist'] = $idpList; $t->data['preferredidp'] = $preferredIdP; $t->data['return'] = $this->returnURL; $t->data['returnIDParam'] = $this->returnIdParam; $t->data['entityID'] = $this->spEntityId; $t->data['urlpattern'] = htmlspecialchars(\SimpleSAML\Utils\HTTP::getSelfURLNoQuery()); $t->data['rememberenabled'] = $this->config->getBoolean('idpdisco.enableremember', false); $t->show(); }
/** * Getter for the LDAP connection object. Created this getter * rather than setting in the constructor to avoid unnecessarily * connecting to LDAP when it might not be needed. * * @return sspmod_ldap_LdapConnection */ protected function getLdap() { // Check if already connected if ($this->ldap) { return $this->ldap; } // Get the connection specific options $hostname = $this->config->getString('ldap.hostname'); $port = $this->config->getInteger('ldap.port', 389); $enable_tls = $this->config->getBoolean('ldap.enable_tls', false); $debug = $this->config->getBoolean('ldap.debug', false); $timeout = $this->config->getInteger('ldap.timeout', 0); $username = $this->config->getString('ldap.username', null); $password = $this->config->getString('ldap.password', null); // Log the LDAP connection SimpleSAML\Logger::debug($this->title . 'Connecting to LDAP server;' . ' Hostname: ' . $hostname . ' Port: ' . $port . ' Enable TLS: ' . ($enable_tls ? 'Yes' : 'No') . ' Debug: ' . ($debug ? 'Yes' : 'No') . ' Timeout: ' . $timeout . ' Username: '******' Password: '******'*', strlen($password))); // Connect to the LDAP server to be queried during processing $this->ldap = new SimpleSAML_Auth_LDAP($hostname, $enable_tls, $debug, $timeout, $port); $this->ldap->bind($username, $password); // All done return $this->ldap; }
/** * Build a authentication response. * * @param array $idp Metadata for the IdP the response is sent from. * @param array $sp Metadata for the SP the response is sent to. * @param string $shire The endpoint on the SP the response is sent to. * @param array|NULL $attributes The attributes which should be included in the response. * @return string The response. */ public function generate(SimpleSAML_Configuration $idp, SimpleSAML_Configuration $sp, $shire, $attributes) { assert('is_string($shire)'); assert('$attributes === NULL || is_array($attributes)'); if ($sp->hasValue('scopedattributes')) { $scopedAttributes = $sp->getArray('scopedattributes'); } elseif ($idp->hasValue('scopedattributes')) { $scopedAttributes = $idp->getArray('scopedattributes'); } else { $scopedAttributes = array(); } $id = SimpleSAML\Utils\Random::generateID(); $issueInstant = SimpleSAML\Utils\Time::generateTimestamp(); // 30 seconds timeskew back in time to allow differing clocks. $notBefore = SimpleSAML\Utils\Time::generateTimestamp(time() - 30); $assertionExpire = SimpleSAML\Utils\Time::generateTimestamp(time() + 60 * 5); # 5 minutes $assertionid = SimpleSAML\Utils\Random::generateID(); $spEntityId = $sp->getString('entityid'); $audience = $sp->getString('audience', $spEntityId); $base64 = $sp->getBoolean('base64attributes', FALSE); $namequalifier = $sp->getString('NameQualifier', $spEntityId); $nameid = SimpleSAML\Utils\Random::generateID(); $subjectNode = '<Subject>' . '<NameIdentifier' . ' Format="urn:mace:shibboleth:1.0:nameIdentifier"' . ' NameQualifier="' . htmlspecialchars($namequalifier) . '"' . '>' . htmlspecialchars($nameid) . '</NameIdentifier>' . '<SubjectConfirmation>' . '<ConfirmationMethod>' . 'urn:oasis:names:tc:SAML:1.0:cm:bearer' . '</ConfirmationMethod>' . '</SubjectConfirmation>' . '</Subject>'; $encodedattributes = ''; if (is_array($attributes)) { $encodedattributes .= '<AttributeStatement>'; $encodedattributes .= $subjectNode; foreach ($attributes as $name => $value) { $encodedattributes .= $this->enc_attribute($name, $value, $base64, $scopedAttributes); } $encodedattributes .= '</AttributeStatement>'; } /* * The SAML 1.1 response message */ $response = '<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" IssueInstant="' . $issueInstant . '" MajorVersion="1" MinorVersion="1" Recipient="' . htmlspecialchars($shire) . '" ResponseID="' . $id . '"> <Status> <StatusCode Value="samlp:Success" /> </Status> <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="' . $assertionid . '" IssueInstant="' . $issueInstant . '" Issuer="' . htmlspecialchars($idp->getString('entityid')) . '" MajorVersion="1" MinorVersion="1"> <Conditions NotBefore="' . $notBefore . '" NotOnOrAfter="' . $assertionExpire . '"> <AudienceRestrictionCondition> <Audience>' . htmlspecialchars($audience) . '</Audience> </AudienceRestrictionCondition> </Conditions> <AuthenticationStatement AuthenticationInstant="' . $issueInstant . '" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified">' . $subjectNode . ' </AuthenticationStatement> ' . $encodedattributes . ' </Assertion> </Response>'; return $response; }
/** * Build a authentication response based on information in the metadata. * * @param SimpleSAML_Configuration $idpMetadata The metadata of the IdP. * @param SimpleSAML_Configuration $spMetadata The metadata of the SP. * @param string $consumerURL The Destination URL of the response. */ private static function buildResponse(SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, $consumerURL) { $signResponse = $spMetadata->getBoolean('saml20.sign.response', NULL); if ($signResponse === NULL) { $signResponse = $idpMetadata->getBoolean('saml20.sign.response', TRUE); } $r = new SAML2_Response(); $r->setIssuer($idpMetadata->getString('entityid')); $r->setDestination($consumerURL); if ($signResponse) { sspmod_saml_Message::addSign($idpMetadata, $spMetadata, $r); } return $r; }
/** * Build an authentication request based on information in the metadata. * * @param SimpleSAML_Configuration $spMetadata The metadata of the service provider. * @param SimpleSAML_Configuration $idpMetadata The metadata of the identity provider. */ public static function buildAuthnRequest(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata) { $ar = new \SAML2\AuthnRequest(); // get the NameIDPolicy to apply. IdP metadata has precedence. $nameIdPolicy = array(); if ($idpMetadata->hasValue('NameIDPolicy')) { $nameIdPolicy = $idpMetadata->getValue('NameIDPolicy'); } elseif ($spMetadata->hasValue('NameIDPolicy')) { $nameIdPolicy = $spMetadata->getValue('NameIDPolicy'); } if (!is_array($nameIdPolicy)) { // handle old configurations where 'NameIDPolicy' was used to specify just the format $nameIdPolicy = array('Format' => $nameIdPolicy); } $nameIdPolicy_cf = SimpleSAML_Configuration::loadFromArray($nameIdPolicy); $policy = array('Format' => $nameIdPolicy_cf->getString('Format', \SAML2\Constants::NAMEID_TRANSIENT), 'AllowCreate' => $nameIdPolicy_cf->getBoolean('AllowCreate', true)); $spNameQualifier = $nameIdPolicy_cf->getString('SPNameQualifier', false); if ($spNameQualifier !== false) { $policy['SPNameQualifier'] = $spNameQualifier; } $ar->setNameIdPolicy($policy); $ar->setForceAuthn($spMetadata->getBoolean('ForceAuthn', FALSE)); $ar->setIsPassive($spMetadata->getBoolean('IsPassive', FALSE)); $protbind = $spMetadata->getValueValidate('ProtocolBinding', array(\SAML2\Constants::BINDING_HTTP_POST, \SAML2\Constants::BINDING_HOK_SSO, \SAML2\Constants::BINDING_HTTP_ARTIFACT, \SAML2\Constants::BINDING_HTTP_REDIRECT), \SAML2\Constants::BINDING_HTTP_POST); /* Shoaib - setting the appropriate binding based on parameter in sp-metadata defaults to HTTP_POST */ $ar->setProtocolBinding($protbind); $ar->setIssuer($spMetadata->getString('entityid')); $ar->setAssertionConsumerServiceIndex($spMetadata->getInteger('AssertionConsumerServiceIndex', NULL)); $ar->setAttributeConsumingServiceIndex($spMetadata->getInteger('AttributeConsumingServiceIndex', NULL)); if ($spMetadata->hasValue('AuthnContextClassRef')) { $accr = $spMetadata->getArrayizeString('AuthnContextClassRef'); $comp = $spMetadata->getValueValidate('AuthnContextComparison', array(\SAML2\Constants::COMPARISON_EXACT, \SAML2\Constants::COMPARISON_MINIMUM, \SAML2\Constants::COMPARISON_MAXIMUM, \SAML2\Constants::COMPARISON_BETTER), \SAML2\Constants::COMPARISON_EXACT); $ar->setRequestedAuthnContext(array('AuthnContextClassRef' => $accr, 'Comparison' => $comp)); } self::addRedirectSign($spMetadata, $idpMetadata, $ar); return $ar; }
/** * Build an authentication request based on information in the metadata. * * @param SimpleSAML_Configuration $spMetadata The metadata of the service provider. * @param SimpleSAML_Configuration $idpMetadata The metadata of the identity provider. */ public static function buildAuthnRequest(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata) { $ar = new SAML2_AuthnRequest(); if ($spMetadata->hasValue('NameIDPolicy')) { $nameIdPolicy = $spMetadata->getString('NameIDPolicy', NULL); } else { $nameIdPolicy = $spMetadata->getString('NameIDFormat', SAML2_Const::NAMEID_TRANSIENT); } if ($nameIdPolicy !== NULL) { $ar->setNameIdPolicy(array('Format' => $nameIdPolicy, 'AllowCreate' => TRUE)); } $ar->setForceAuthn($spMetadata->getBoolean('ForceAuthn', FALSE)); $ar->setIsPassive($spMetadata->getBoolean('IsPassive', FALSE)); $protbind = $spMetadata->getValueValidate('ProtocolBinding', array(SAML2_Const::BINDING_HTTP_POST, SAML2_Const::BINDING_HOK_SSO, SAML2_Const::BINDING_HTTP_ARTIFACT, SAML2_Const::BINDING_HTTP_REDIRECT), SAML2_Const::BINDING_HTTP_POST); /* Shoaib - setting the appropriate binding based on parameter in sp-metadata defaults to HTTP_POST */ $ar->setProtocolBinding($protbind); $ar->setIssuer($spMetadata->getString('entityid')); $ar->setAssertionConsumerServiceIndex($spMetadata->getInteger('AssertionConsumerServiceIndex', NULL)); $ar->setAttributeConsumingServiceIndex($spMetadata->getInteger('AttributeConsumingServiceIndex', NULL)); if ($spMetadata->hasValue('AuthnContextClassRef')) { $accr = $spMetadata->getArrayizeString('AuthnContextClassRef'); $ar->setRequestedAuthnContext(array('AuthnContextClassRef' => $accr)); } self::addRedirectSign($spMetadata, $idpMetadata, $ar); return $ar; }
/** * Send a SAML1 SSO request to an IdP. * * @param SimpleSAML_Configuration $idpMetadata The metadata of the IdP. * @param array $state The state array for the current authentication. */ private function startSSO1(SimpleSAML_Configuration $idpMetadata, array $state) { $idpEntityId = $idpMetadata->getString('entityid'); $state['saml:idp'] = $idpEntityId; $ar = new SimpleSAML_XML_Shib13_AuthnRequest(); $ar->setIssuer($this->entityId); $id = SimpleSAML_Auth_State::saveState($state, 'saml:sp:sso'); $ar->setRelayState($id); $useArtifact = $idpMetadata->getBoolean('saml1.useartifact', NULL); if ($useArtifact === NULL) { $useArtifact = $this->metadata->getBoolean('saml1.useartifact', FALSE); } if ($useArtifact) { $shire = SimpleSAML\Module::getModuleURL('saml/sp/saml1-acs.php/' . $this->authId . '/artifact'); } else { $shire = SimpleSAML\Module::getModuleURL('saml/sp/saml1-acs.php/' . $this->authId); } $url = $ar->createRedirect($idpEntityId, $shire); SimpleSAML\Logger::debug('Starting SAML 1 SSO to ' . var_export($idpEntityId, TRUE) . ' from ' . var_export($this->entityId, TRUE) . '.'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url); }
/** * Generate an Instance ID based on the database configuration. * * @param \SimpleSAML_Configuration $config Configuration class * * @return string $instanceId */ private static function generateInstanceId($config) { $assembledConfig = array('master' => array('database.dsn' => $config->getString('database.dsn'), 'database.username' => $config->getString('database.username', null), 'database.password' => $config->getString('database.password', null), 'database.prefix' => $config->getString('database.prefix', ''), 'database.persistent' => $config->getBoolean('database.persistent', false)), 'slaves' => $config->getArray('database.slaves', array())); return sha1(serialize($assembledConfig)); }
/** * Build a authentication response based on information in the metadata. * * @param SimpleSAML_Configuration $srcMetadata The metadata of the sender (IdP). * @param SimpleSAML_Configuration $dstMetadata The metadata of the recipient (SP). */ public static function buildResponse(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, $consumerURL) { $signResponse = $dstMetadata->getBoolean('saml20.sign.response', NULL); if ($signResponse === NULL) { $signResponse = $srcMetadata->getBoolean('saml20.sign.response', TRUE); } $r = new SAML2_Response(); $r->setIssuer($srcMetadata->getString('entityid')); $r->setDestination($consumerURL); if ($signResponse) { self::addSign($srcMetadata, $dstMetadata, $r); } return $r; }