/** * Set the assertion. * * @param \SAML2\Assertion $assertion The assertion. * @param XMLSecurityKey $key The key we should use to encrypt the assertion. * @throws \Exception */ public function setAssertion(Assertion $assertion, XMLSecurityKey $key) { $xml = $assertion->toXML(); Utils::getContainer()->debugMessage($xml, 'encrypt'); $enc = new XMLSecEnc(); $enc->setNode($xml); $enc->type = XMLSecEnc::Element; switch ($key->type) { case XMLSecurityKey::TRIPLEDES_CBC: case XMLSecurityKey::AES128_CBC: case XMLSecurityKey::AES192_CBC: case XMLSecurityKey::AES256_CBC: $symmetricKey = $key; break; case XMLSecurityKey::RSA_1_5: case XMLSecurityKey::RSA_OAEP_MGF1P: $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); $symmetricKey->generateSessionKey(); $enc->encryptKey($key, $symmetricKey); break; default: throw new \Exception('Unknown key type for encryption: ' . $key->type); } $this->encryptedData = $enc->encryptNode($symmetricKey); }
public function validate(Assertion $assertion, Result $result) { $notBeforeTimestamp = $assertion->getNotBefore(); if ($notBeforeTimestamp && $notBeforeTimestamp > Temporal::getTime() + 60) { $result->addError('Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.'); } }
public function validate(Assertion $assertion, Result $result) { $notValidOnOrAfterTimestamp = $assertion->getNotOnOrAfter(); if ($notValidOnOrAfterTimestamp && $notValidOnOrAfterTimestamp <= Temporal::getTime() - 60) { $result->addError('Received an assertion that has expired. Check clock synchronization on IdP and SP.'); } }
public function validate(Assertion $assertion, Result $result) { $sessionNotOnOrAfterTimestamp = $assertion->getSessionNotOnOrAfter(); $currentTime = Temporal::getTime(); if ($sessionNotOnOrAfterTimestamp && $sessionNotOnOrAfterTimestamp <= $currentTime - 60) { $result->addError('Received an assertion with a session that has expired. Check clock synchronization on IdP and SP.'); } }
public function validate(Assertion $assertion, Result $result) { $intendedAudiences = $assertion->getValidAudiences(); if ($intendedAudiences === null) { return; } $entityId = $this->serviceProvider->getEntityId(); if (!in_array($entityId, $intendedAudiences)) { $result->addError(sprintf('The configured Service Provider [%s] is not a valid audience for the assertion. Audiences: [%s]', $entityId, implode('], [', $intendedAudiences))); } }
public function transform(Assertion $assertion) { if (!$this->identityProvider->hasBase64EncodedAttributes()) { return $assertion; } $attributes = $assertion->getAttributes(); $keys = array_keys($attributes); $decoded = array_map(array($this, 'decodeValue'), $attributes); $attributes = array_combine($keys, $decoded); $assertion->setAttributes($attributes); }
public static function handleLoginRequest(IPerson $Person) { try { $binding = Binding::getCurrentBinding(); } catch (Exception $e) { return static::throwUnauthorizedError('Cannot obtain SAML2 binding'); } $request = $binding->receive(); // build response $response = new Response(); $response->setInResponseTo($request->getId()); $response->setRelayState($request->getRelayState()); $response->setDestination($request->getAssertionConsumerServiceURL()); // build assertion $assertion = new Assertion(); $assertion->setIssuer(static::$issuer); $assertion->setSessionIndex(ContainerSingleton::getInstance()->generateId()); $assertion->setNotBefore(time() - 30); $assertion->setNotOnOrAfter(time() + 300); $assertion->setAuthnContext(SAML2_Constants::AC_PASSWORD); // build subject confirmation $sc = new SubjectConfirmation(); $sc->Method = SAML2_Constants::CM_BEARER; $sc->SubjectConfirmationData = new SubjectConfirmationData(); $sc->SubjectConfirmationData->NotOnOrAfter = $assertion->getNotOnOrAfter(); $sc->SubjectConfirmationData->Recipient = $request->getAssertionConsumerServiceURL(); $sc->SubjectConfirmationData->InResponseTo = $request->getId(); $assertion->setSubjectConfirmation([$sc]); // set NameID $assertion->setNameId(['Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', 'Value' => $Person->Username . '@' . static::$issuer]); // set additional attributes $assertion->setAttributes(['User.Email' => [$Person->Email], 'User.Username' => [$Person->Username]]); // attach assertion to response $response->setAssertions([$assertion]); // create signature $privateKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']); $privateKey->loadKey(static::$privateKey); $response->setSignatureKey($privateKey); $response->setCertificates([static::$certificate]); // prepare response $responseXML = $response->toSignedXML(); $responseString = $responseXML->ownerDocument->saveXML($responseXML); // dump response and quit # header('Content-Type: text/xml'); # die($responseString); // send response $responseBinding = new HTTPPost(); $responseBinding->send($response); }
public function transform(Assertion $assertion) { if (!$assertion->isNameIdEncrypted()) { return $assertion; } $decryptionKeys = $this->privateKeyLoader->loadDecryptionKeys($this->identityProvider, $this->serviceProvider); $blacklistedKeys = $this->identityProvider->getBlacklistedAlgorithms(); if (is_null($blacklistedKeys)) { $blacklistedKeys = $this->serviceProvider->getBlacklistedAlgorithms(); } foreach ($decryptionKeys as $index => $key) { try { $assertion->decryptNameId($key, $blacklistedKeys); $this->logger->debug(sprintf('Decrypted assertion NameId with key "#%d"', $index)); } catch (\Exception $e) { $this->logger->debug(sprintf('Decrypting assertion NameId with key "#%d" failed, "%s" thrown: "%s"', $index, get_class($e), $e->getMessage())); } } if ($assertion->isNameIdEncrypted()) { throw new NotDecryptedException('Could not decrypt the assertion NameId with the configured keys, see the debug log for information'); } return $assertion; }
/** * Decrypt an assertion. * * This function takes in a \SAML2\Assertion and decrypts it if it is encrypted. * If it is unencrypted, and encryption is enabled in the metadata, an exception * will be throws. * * @param SimpleSAML_Configuration $srcMetadata The metadata of the sender (IdP). * @param SimpleSAML_Configuration $dstMetadata The metadata of the recipient (SP). * @param \SAML2\Assertion|\SAML2\EncryptedAssertion $assertion The assertion we are decrypting. * @return \SAML2\Assertion The assertion. */ private static function decryptAssertion(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, $assertion) { assert('$assertion instanceof \\SAML2\\Assertion || $assertion instanceof \\SAML2\\EncryptedAssertion'); if ($assertion instanceof \SAML2\Assertion) { $encryptAssertion = $srcMetadata->getBoolean('assertion.encryption', NULL); if ($encryptAssertion === NULL) { $encryptAssertion = $dstMetadata->getBoolean('assertion.encryption', FALSE); } if ($encryptAssertion) { /* The assertion was unencrypted, but we have encryption enabled. */ throw new Exception('Received unencrypted assertion, but encryption was enabled.'); } return $assertion; } try { $keys = self::getDecryptionKeys($srcMetadata, $dstMetadata); } catch (Exception $e) { throw new SimpleSAML_Error_Exception('Error decrypting assertion: ' . $e->getMessage()); } $blacklist = self::getBlacklistedAlgorithms($srcMetadata, $dstMetadata); $lastException = NULL; foreach ($keys as $i => $key) { try { $ret = $assertion->getAssertion($key, $blacklist); SimpleSAML\Logger::debug('Decryption with key #' . $i . ' succeeded.'); return $ret; } catch (Exception $e) { SimpleSAML\Logger::debug('Decryption with key #' . $i . ' failed with exception: ' . $e->getMessage()); $lastException = $e; } } throw $lastException; }
public function testHasEncryptedAttributes() { $document = new \DOMDocument(); $document->loadXML(<<<XML <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_93af655219464fb403b34436cfb0c5cb1d9a5502" IssueInstant="1970-01-01T01:33:31Z"> <saml:Issuer>Provider</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">s00000000:123456789</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2011-08-31T08:51:05Z" Recipient="https://sp.example.com/assertion_consumer" InResponseTo="_13603a6565a69297e9809175b052d115965121c8" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotOnOrAfter="2011-08-31T08:51:05Z" NotBefore="2011-08-31T08:51:05Z"> <saml:AudienceRestriction> <saml:Audience>ServiceProvider</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2011-08-31T08:51:05Z" SessionIndex="_93af655219464fb403b34436cfb0c5cb1d9a5502"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </saml:AuthnContext> <saml:SubjectLocality Address="127.0.0.1"/> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="urn:ServiceID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="urn:EntityConcernedID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="urn:EntityConcernedSubID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> <saml:EncryptedAttribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element" Id="_F39625AF68B4FC078CC7582D28D05D9C"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <xenc:EncryptedKey> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/> <ds:KeyInfo> <ds:KeyName>62355fbd1f624503c5c9677402ecca00ef1f6277</ds:KeyName> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue>K0mBLxfLziKVUKEAOYe7D6uVSCPy8vyWVh3RecnPES+8QkAhOuRSuE/LQpFr0huI/iCEy9pde1QgjYDLtjHcujKi2xGqW6jkXW/EuKomqWPPA2xYs1fpB1su4aXUOQB6OJ70/oDcOsy834ghFaBWilE8fqyDBUBvW+2IvaMUZabwN/s9mVkWzM3r30tlkhLK7iOrbGAldIHwFU5z7PPR6RO3Y3fIxjHU40OnLsJc3xIqdLH3fXpC0kgi5UspLdq14e5OoXjLoPG3BO3zwOAIJ8XNBWY5uQof6KrKbcvtZSY0fMvPYhYfNjtRFy8y49ovL9fwjCRTDlT5+aHqsCTBrw==</xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedKey> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue>ZzCu6axGgAYZHVf77NX8apZKB/GJDeuV6bFByBS0AIgiXkvDUAmLCpabTAWBM+yz19olA6rryuOfr82ev2bzPNURvm4SYxahvuL4Pibn5wJky0Bl54VqmcU+Aqj0dAvOgqG1y3X4wO9n9bRsTv6921m0eqRAFph8kK8L9hirK1BxYBYj2RyFCoFDPxVZ5wyra3q4qmE4/ELQpFP6mfU8LXb0uoWJUjGUelS2Aa7bZis8zEpwov4CwtlNjltQih4mv7ttCAfYqcQIFzBTB+DAa0+XggxCLcdB3+mQiRcECBfwHHJ7gRmnuBEgeWT3CGKa3Nb7GMXOfuxFKF5pIehWgo3kdNQLalor8RVW6I8P/I8fQ33Fe+NsHVnJ3zwSA//a</xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </saml:EncryptedAttribute> </saml:AttributeStatement> </saml:Assertion> XML ); $assertion = new Assertion($document->firstChild); $this->assertTrue($assertion->hasEncryptedAttributes()); }
/** * @group Assertion */ public function testCorrectSignatureMethodCanBeExtracted() { $document = new \DOMDocument(); $document->loadXML(<<<XML <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_93af655219464fb403b34436cfb0c5cb1d9a5502" IssueInstant="1970-01-01T01:33:31Z"> <saml:Issuer>Provider</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">s00000000:123456789</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2011-08-31T08:51:05Z" Recipient="https://sp.example.com/assertion_consumer" InResponseTo="_13603a6565a69297e9809175b052d115965121c8" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotOnOrAfter="2011-08-31T08:51:05Z" NotBefore="2011-08-31T08:51:05Z"> <saml:AudienceRestriction> <saml:Audience>ServiceProvider</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2011-08-31T08:51:05Z" SessionIndex="_93af655219464fb403b34436cfb0c5cb1d9a5502"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </saml:AuthnContext> <saml:SubjectLocality Address="127.0.0.1"/> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="urn:ServiceID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="urn:EntityConcernedID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="urn:EntityConcernedSubID"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> XML ); $privateKey = CertificatesMock::getPrivateKey(); $unsignedAssertion = new Assertion($document->firstChild); $unsignedAssertion->setSignatureKey($privateKey); $unsignedAssertion->setCertificates(array(CertificatesMock::PUBLIC_KEY_PEM)); $signedAssertion = new Assertion($unsignedAssertion->toXML()); $signatureMethod = $signedAssertion->getSignatureMethod(); $this->assertEquals($privateKey->getAlgorith(), $signatureMethod); }
public function testTypedEncryptedAttributeValuesAreParsedCorrectly() { $xml = <<<XML <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.0" ID="_93af655219464fb403b34436cfb0c5cb1d9a5502" IssueInstant="1970-01-01T01:33:31Z"> <saml:Issuer>Provider</saml:Issuer> <saml:Conditions/> <saml:AttributeStatement> <saml:Attribute Name="urn:some:string"> <saml:AttributeValue xsi:type="xs:string">string</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="urn:some:integer"> <saml:AttributeValue xsi:type="xs:integer">42</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> XML; $privateKey = CertificatesMock::getPublicKey(); $assertion = new Assertion(DOMDocumentFactory::fromString($xml)->firstChild); $assertion->setEncryptionKey($privateKey); $assertion->setEncryptedAttributes(true); $encryptedAssertion = $assertion->toXML()->ownerDocument->saveXML(); $assertionToVerify = new Assertion(DOMDocumentFactory::fromString($encryptedAssertion)->firstChild); $this->assertTrue($assertionToVerify->hasEncryptedAttributes()); $assertionToVerify->decryptAttributes(CertificatesMock::getPrivateKey()); $attributes = $assertionToVerify->getAttributes(); $this->assertInternalType('int', $attributes['urn:some:integer'][0]); $this->assertInternalType('string', $attributes['urn:some:string'][0]); $this->assertXmlStringEqualsXmlString($xml, $assertionToVerify->toXML()->ownerDocument->saveXML()); }
/** * Test Exception when trying to get encrypted NameId without * decrypting it first. */ public function testRetrieveEncryptedNameIdException() { $xml = <<<XML <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_593e33ddf86449ce4d4c22b60ac48e067d98a0b2bf" Version="2.0" IssueInstant="2010-03-05T13:34:28Z" > <saml:Issuer>testIssuer</saml:Issuer> <saml:Subject> <saml:EncryptedID> <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Type="http://www.w3.org/2001/04/xmlenc#Element"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/> <dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> <xenc:EncryptedKey><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> <xenc:CipherData><xenc:CipherValue>Y78/DDeSkI4qECUPXJM1cWUTaYVglxnqDRpjcqd6zdIR6yWMwIzUCd+fa9KhKutN4kN1i/koSMNmk+c6uOXSi0Xuohth61eU9oIwLl6mKZwThXEQiuphAtMVPXtooKfU1l58+xWiiO2IidYmtb1vCcVD0hZwnVv28kxrMQdQmzw=</xenc:CipherValue></xenc:CipherData> </xenc:EncryptedKey> </dsig:KeyInfo> <xenc:CipherData> <xenc:CipherValue>cfQoRV0xf+D5bOQs+8icVEkWX4MRNxl1MhImqO/GwYxjCwj0AH/9O4kr2v4WZ4MC3zHhUjcq4HO70/xrkzQVMN9pBsF2yv9sUuN2rEPd8k/Oj/OA3X4xGNywxoJILioh56OyNkFK/q4WRptvvSQV1vPc0G5y65MZBiR2fy+L+ukBJ8mnzxL7aIIEKRxNa0beKdrrZ2twWH3Uwn3UW5LcSefaY+VHcM/9I4Xb7U5QWxRXzBOEa6v/a3cZ/TmlXYkj</xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </saml:EncryptedID> </saml:Subject> </saml:Assertion> XML; $document = DOMDocumentFactory::fromString($xml); $assertion = new Assertion($document->documentElement); $this->setExpectedException('Exception', "Attempted to retrieve encrypted NameID without decrypting it first"); $assertion->getNameID(); }