Skip to content

Commit bb9a2a0

Browse files
committed
Fix #356. Support 'x509cert' and 'privateKey' on signMetadata security setting
1 parent 2aadebf commit bb9a2a0

5 files changed

Lines changed: 81 additions & 22 deletions

File tree

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,14 @@ $advancedSettings = array(
420420
'logoutResponseSigned' => false,
421421

422422
/* Sign the Metadata
423-
False || True (use sp certs) || array(
424-
keyFileName => 'metadata.key',
425-
certFileName => 'metadata.crt'
426-
)
423+
False || True (use sp certs) || array (
424+
'keyFileName' => 'metadata.key',
425+
'certFileName' => 'metadata.crt'
426+
)
427+
|| array (
428+
'x509cert' => '',
429+
'privateKey' => ''
430+
)
427431
*/
428432
'signMetadata' => false,
429433

advanced_settings_example.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@
3333
'logoutResponseSigned' => false,
3434

3535
/* Sign the Metadata
36-
False || True (use sp certs) || array(
37-
keyFileName => 'metadata.key',
38-
certFileName => 'metadata.crt'
39-
)
36+
False || True (use sp certs) || array (
37+
'keyFileName' => 'metadata.key',
38+
'certFileName' => 'metadata.crt'
39+
)
40+
|| array (
41+
'x509cert' => '',
42+
'privateKey' => ''
43+
)
4044
*/
4145
'signMetadata' => false,
4246

src/Saml2/Metadata.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public static function builder($sp, $authnsign = false, $wsign = false, $validUn
200200
* @param string $digestAlgorithm Digest algorithm method
201201
*
202202
* @return string Signed Metadata
203-
*
203+
*
204204
* @throws Exception
205205
*/
206206
public static function signMetadata($metadata, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA256, $digestAlgorithm = XMLSecurityDSig::SHA256)
@@ -217,7 +217,7 @@ public static function signMetadata($metadata, $key, $cert, $signAlgorithm = XML
217217
* @param bool $wantsEncrypted Whether to include the KeyDescriptor for encryption
218218
*
219219
* @return string Metadata with KeyDescriptors
220-
*
220+
*
221221
* @throws Exception
222222
*/
223223
public static function addX509KeyDescriptors($metadata, $cert, $wantsEncrypted = true)

src/Saml2/Settings.php

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,10 @@ public function checkSPSettings(array $settings)
596596
}
597597

598598
if (isset($security['signMetadata']) && is_array($security['signMetadata'])) {
599-
if (!isset($security['signMetadata']['keyFileName'])
600-
|| !isset($security['signMetadata']['certFileName'])
599+
if ((!isset($security['signMetadata']['keyFileName'])
600+
|| !isset($security['signMetadata']['certFileName'])) &&
601+
(!isset($security['signMetadata']['privateKey'])
602+
|| !isset($security['signMetadata']['x509cert']))
601603
) {
602604
$errors[] = 'sp_signMetadata_invalid';
603605
}
@@ -800,7 +802,7 @@ public function shouldCompressResponses()
800802
*
801803
* @param bool $alwaysPublishEncryptionCert When 'true', the returned
802804
* metadata will always include an 'encryption' KeyDescriptor. Otherwise,
803-
* the 'encryption' KeyDescriptor will only be included if
805+
* the 'encryption' KeyDescriptor will only be included if
804806
* $advancedSettings['security']['wantNameIdEncrypted'] or
805807
* $advancedSettings['security']['wantAssertionsEncrypted'] are enabled.
806808
* @param int|null $validUntil Metadata's valid time
@@ -851,15 +853,8 @@ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil
851853
Error::PUBLIC_CERT_FILE_NOT_FOUND
852854
);
853855
}
854-
} else {
855-
if (!isset($this->_security['signMetadata']['keyFileName'])
856-
|| !isset($this->_security['signMetadata']['certFileName'])
857-
) {
858-
throw new Error(
859-
'Invalid Setting: signMetadata value of the sp is not valid',
860-
Error::SETTINGS_INVALID_SYNTAX
861-
);
862-
}
856+
} else if (isset($this->_security['signMetadata']['keyFileName']) &&
857+
isset($this->_security['signMetadata']['certFileName'])) {
863858
$keyFileName = $this->_security['signMetadata']['keyFileName'];
864859
$certFileName = $this->_security['signMetadata']['certFileName'];
865860

@@ -883,6 +878,29 @@ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil
883878
}
884879
$keyMetadata = file_get_contents($keyMetadataFile);
885880
$certMetadata = file_get_contents($certMetadataFile);
881+
} else if (isset($this->_security['signMetadata']['privateKey']) &&
882+
isset($this->_security['signMetadata']['x509cert'])) {
883+
$keyMetadata = Utils::formatPrivateKey($this->_security['signMetadata']['privateKey']);
884+
$certMetadata = Utils::formatCert($this->_security['signMetadata']['x509cert']);
885+
if (!$keyMetadata) {
886+
throw new Error(
887+
'Private key not found.',
888+
Error::PRIVATE_KEY_FILE_NOT_FOUND
889+
);
890+
}
891+
892+
if (!$certMetadata) {
893+
throw new Error(
894+
'Public cert not found.',
895+
Error::PUBLIC_CERT_FILE_NOT_FOUND
896+
);
897+
}
898+
} else {
899+
throw new Error(
900+
'Invalid Setting: signMetadata value of the sp is not valid',
901+
Error::SETTINGS_INVALID_SYNTAX
902+
);
903+
886904
}
887905

888906
$signatureAlgorithm = $this->_security['signatureAlgorithm'];

tests/src/OneLogin/Saml2/SettingsTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,17 @@ public function testCheckSettings()
374374
$this->assertContains('organization_not_enought_data', $e->getMessage());
375375
$this->assertContains('contact_type_invalid', $e->getMessage());
376376
}
377+
378+
$settingsInfo['security']['signMetadata'] = ['privateKey' => file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.key')];
379+
380+
try {
381+
$settings = new Settings($settingsInfo);
382+
$this->fail('Error was not raised');
383+
} catch (Error $e) {
384+
$this->assertContains('sp_signMetadata_invalid', $e->getMessage());
385+
$this->assertContains('organization_not_enought_data', $e->getMessage());
386+
$this->assertContains('contact_type_invalid', $e->getMessage());
387+
}
377388
}
378389

379390
/**
@@ -567,6 +578,28 @@ public function testGetSPMetadataSigned()
567578
$this->assertContains('<ds:Reference', $metadata2);
568579
$this->assertContains('<ds:KeyInfo><ds:X509Data><ds:X509Certificate>', $metadata2);
569580

581+
$cert = file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.crt');
582+
$settingsInfo['security']['signMetadata'] = [
583+
'privateKey' => file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.key'),
584+
'x509cert' => $cert,
585+
];
586+
$settings3 = new Settings($settingsInfo);
587+
$metadata3 = $settings3->getSPMetadata();
588+
589+
$this->assertNotEmpty($metadata3);
590+
$this->assertContains('<md:SPSSODescriptor', $metadata3);
591+
$this->assertContains('entityID="http://stuff.com/endpoints/metadata.php"', $metadata3);
592+
$this->assertContains('AuthnRequestsSigned="false"', $metadata3);
593+
$this->assertContains('WantAssertionsSigned="false"', $metadata3);
594+
$this->assertContains('<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://stuff.com/endpoints/endpoints/acs.php" index="1"/>', $metadata3);
595+
$this->assertContains('<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://stuff.com/endpoints/endpoints/sls.php"/>', $metadata3);
596+
$this->assertContains('<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>', $metadata3);
597+
598+
$this->assertContains('<ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>', $metadata3);
599+
$this->assertContains('<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>', $metadata3);
600+
$this->assertContains('<ds:Reference', $metadata3);
601+
$this->assertContains('<ds:KeyInfo><ds:X509Data><ds:X509Certificate>', $metadata3);
602+
$this->assertContains(Utils::formatCert($cert, false), $metadata3);
570603
}
571604

572605
/**

0 commit comments

Comments
 (0)