public function signQuery($query, $md) { /* Check if signing of HTTP-Redirect messages is enabled. */ if (empty($md['request.signing'])) { return $query; } /* Load the private key. */ if (empty($md['privatekey'])) { throw new Exception('SAML: If you set request.signing to be true in the metadata, you also have to add the privatekey parameter.'); } /* Sign the query string. According to the specification, the string which should be * signed is the concatenation of the following query parameters (in order): * - SAMLRequest/SAMLResponse * - RelayState (if present) * - SigAlg * * We assume that the query string now contains only the two first parameters. */ /* Append the signature algorithm. We always use RSA-SHA1. */ $algURI = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'; $query = $query . "&" . "SigAlg=" . urlencode($algURI); $xmlseckey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); /* Set the passphrase which should be used to open the key, if this attribute is * set in the metadata. */ if (array_key_exists('privatekey_pass', $md)) { $xmlseckey->passphrase = $md['privatekey_pass']; } $xmlseckey->loadKey($md['privatekey']); $signature = $xmlseckey->signData($query); $query = $query . "&" . "Signature=" . urlencode(base64_encode($signature)); return $query; }
/** * Generates the Signature for a SAML Response * * @param string $samlResponse The SAML Response * @param string $relayState The RelayState * @param string $signAlgorithm Signature algorithm method * * @return string A base64 encoded signature */ public function buildResponseSignature($samlResponse, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA1) { if (!$this->_settings->checkSPCerts()) { throw new OneLogin_Saml2_Error("Trying to sign the SAML Response but can't load the SP certs", OneLogin_Saml2_Error::SP_CERTS_NOT_FOUND); } $key = $this->_settings->getSPkey(); $objKey = new XMLSecurityKey($signAlgorithm, array('type' => 'private')); $objKey->loadKey($key, false); $msg = 'SAMLResponse=' . urlencode($samlResponse); $msg .= '&RelayState=' . urlencode($relayState); $msg .= '&SigAlg=' . urlencode($signAlgorithm); $signature = $objKey->signData($msg); return base64_encode($signature); }
/** * Constructs the AuthnRequest object. * * @param OneLogin_Saml2_Settings $settings Settings * @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true' * @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true' */ public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = false, $isPassive = false) { $this->_settings = $settings; $spData = $this->_settings->getSPData(); $idpData = $this->_settings->getIdPData(); $security = $this->_settings->getSecurityData(); $id = OneLogin_Saml2_Utils::generateUniqueID(); $issueInstant = OneLogin_Saml2_Utils::parseTime2SAML(time()); $nameIDPolicyFormat = $spData['NameIDFormat']; if (isset($security['wantNameIdEncrypted']) && $security['wantNameIdEncrypted']) { $nameIDPolicyFormat = OneLogin_Saml2_Constants::NAMEID_ENCRYPTED; } $providerNameStr = ''; $organizationData = $settings->getOrganization(); if (!empty($organizationData)) { $langs = array_keys($organizationData); if (in_array('en-US', $langs)) { $lang = 'en-US'; } else { $lang = $langs[0]; } if (isset($organizationData[$lang]['displayname']) && !empty($organizationData[$lang]['displayname'])) { $providerNameStr = <<<PROVIDERNAME ProviderName="{$organizationData[$lang]['displayname']}" PROVIDERNAME; } } $forceAuthnStr = ''; if ($forceAuthn) { $forceAuthnStr = <<<FORCEAUTHN ForceAuthn="true" FORCEAUTHN; } $isPassiveStr = ''; if ($isPassive) { $isPassiveStr = <<<ISPASSIVE IsPassive="true" ISPASSIVE; } $requestedAuthnStr = ''; if (isset($security['requestedAuthnContext']) && $security['requestedAuthnContext'] !== false) { if ($security['requestedAuthnContext'] === true) { $requestedAuthnStr = <<<REQUESTEDAUTHN <samlp:RequestedAuthnContext Comparison="exact"> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </samlp:RequestedAuthnContext> REQUESTEDAUTHN; } else { $requestedAuthnStr .= " <samlp:RequestedAuthnContext Comparison=\"exact\">\n"; foreach ($security['requestedAuthnContext'] as $contextValue) { $requestedAuthnStr .= " <saml:AuthnContextClassRef>" . $contextValue . "</saml:AuthnContextClassRef>\n"; } $requestedAuthnStr .= ' </samlp:RequestedAuthnContext>'; } } $signature = ''; if (isset($security['authnRequestsSigned']) && $security['authnRequestsSigned']) { $key = $this->_settings->getSPkey(); $objKey = new XMLSecurityKey($security['signatureAlgorithm'], array('type' => 'private')); $objKey->loadKey($key, false); $signatureValue = $objKey->signData(time()); $signatureValue = base64_encode($signatureValue); $digestValue = base64_encode(sha1(time())); $x509Cert = $this->_settings->getSPcert(); $x509Cert = OneLogin_Saml2_Utils::formatCert($x509Cert, false); $signature = <<<SIGNATURE <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <ds:Reference> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue>{$digestValue}</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>asd{$signatureValue}</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>{$x509Cert}</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> SIGNATURE; } $request = <<<AUTHNREQUEST <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{$id}" Version="2.0" {$providerNameStr}{$forceAuthnStr}{$isPassiveStr} IssueInstant="{$issueInstant}" Destination="{$idpData['singleSignOnService']['url']}" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="{$spData['assertionConsumerService']['url']}"> <saml:Issuer>{$spData['entityId']}</saml:Issuer> {$signature} <samlp:NameIDPolicy Format="{$nameIDPolicyFormat}" AllowCreate="true" /> {$requestedAuthnStr} </samlp:AuthnRequest> AUTHNREQUEST; $this->_id = $id; $this->_authnRequest = $request; }