Skip to content

Commit 411f7ab

Browse files
authored
Merge pull request #358 from mwey/feature-slo-response-location
Feature support: SLO ResponseLocation
2 parents 35efa30 + 7dc2a85 commit 411f7ab

File tree

10 files changed

+59
-10
lines changed

10 files changed

+59
-10
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,9 @@ $settings = array (
375375
'singleLogoutService' => array (
376376
// URL Location of the IdP where SLO Request will be sent.
377377
'url' => '',
378+
// URL location of the IdP where the SP will send the SLO Response (ResponseLocation)
379+
// if not set, url for the SLO Request will be used
380+
'responseUrl' => '',
378381
// SAML protocol binding to be used when returning the <Response>
379382
// message. OneLogin Toolkit supports the HTTP-Redirect binding
380383
// only for this endpoint.

lib/Saml2/Auth.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ public function processSLO($keepLocalSession = false, $requestId = null, $retrie
285285
$parameters['Signature'] = $signature;
286286
}
287287

288-
return $this->redirectTo($this->getSLOurl(), $parameters, $stay);
288+
return $this->redirectTo($this->getSLOResponseUrl(), $parameters, $stay);
289289
}
290290
} else {
291291
$this->_errors[] = 'invalid_binding';
@@ -581,6 +581,20 @@ public function getSLOurl()
581581
return $url;
582582
}
583583

584+
/**
585+
* Gets the SLO response url.
586+
*
587+
* @return string|null The response url of the Single Logout Service
588+
*/
589+
public function getSLOResponseUrl()
590+
{
591+
$idpData = $this->_settings->getIdPData();
592+
if (isset($idpData['singleLogoutService']) && isset($idpData['singleLogoutService']['responseUrl'])) {
593+
return $idpData['singleLogoutService']['responseUrl'];
594+
}
595+
return $this->getSLOurl();
596+
}
597+
584598
/**
585599
* Gets the ID of the last AuthNRequest or LogoutRequest generated by the Service Provider.
586600
*

lib/Saml2/IdPMetadataParser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public static function parseXML($xml, $entityId = null, $desiredNameIdFormat = n
140140
if ($sloNodes->length > 0) {
141141
$metadataInfo['idp']['singleLogoutService'] = array(
142142
'url' => $sloNodes->item(0)->getAttribute('Location'),
143+
'responseUrl' => $sloNodes->item(0)->getAttribute('ResponseLocation'),
143144
'binding' => $sloNodes->item(0)->getAttribute('Binding')
144145
);
145146
}

lib/Saml2/Settings.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,14 @@ public function checkIdPSettings($settings)
531531
$errors[] = 'idp_slo_url_invalid';
532532
}
533533

534+
if (isset($idp['singleLogoutService'])
535+
&& isset($idp['singleLogoutService']['responseUrl'])
536+
&& !empty($idp['singleLogoutService']['responseUrl'])
537+
&& !filter_var($idp['singleLogoutService']['responseUrl'], FILTER_VALIDATE_URL)
538+
) {
539+
$errors[] = 'idp_slo_response_url_invalid';
540+
}
541+
534542
if (isset($settings['security'])) {
535543
$security = $settings['security'];
536544

settings_example.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@
9393
'singleLogoutService' => array (
9494
// URL Location of the IdP where the SP will send the SLO Request
9595
'url' => '',
96+
// URL location of the IdP where the SP will send the SLO Response (ResponseLocation)
97+
// if not set, url for the SLO Request will be used
98+
'responseUrl' => '',
9699
// SAML protocol binding to be used when returning the <Response>
97100
// message. Onelogin Toolkit supports for this endpoint the
98101
// HTTP-Redirect binding only

tests/data/metadata/idp/metadata.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ WQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw==</ds:X509Certificate>
6868
</ds:X509Data>
6969
</ds:KeyInfo>
7070
</KeyDescriptor>
71-
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.examle.com/saml/slo"/>
71+
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.examle.com/saml/slo" ResponseLocation="https://idp.examle.com/saml/slr"/>
7272
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
7373
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.examle.com/saml/sso"/>
7474
</IDPSSODescriptor>

tests/settings/settings1.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
),
2020
'singleLogoutService' => array (
2121
'url' => 'http://idp.example.com/SingleLogoutService.php',
22+
'responseUrl' => 'http://idp.example.com/SingleLogoutServiceResponse.php',
2223
),
2324
'x509cert' => 'MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo',
2425
),

tests/src/OneLogin/Saml2/AuthTest.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ public function testGetSLOurl()
7979
$this->assertEquals($this->_auth->getSLOurl(), $sloUrl);
8080
}
8181

82+
/**
83+
* Tests the getSLOResponseUrl method of the OneLogin_Saml2_Auth class
84+
*
85+
* @covers OneLogin_Saml2_Auth::getSLOurl
86+
*/
87+
public function testGetSLOResponseUrl()
88+
{
89+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
90+
$this->assertEquals($this->_auth->getSLOResponseUrl(), $sloResponseUrl);
91+
}
92+
8293
/**
8394
* Tests the processResponse method of the OneLogin_Saml2_Auth class
8495
* Case No Response, An exception is throw
@@ -548,8 +559,8 @@ public function testProcessSLORequestInvalidValid()
548559
$parsedQuery = getParamsFromUrl($targetUrl);
549560

550561
$this->assertEmpty($this->_auth->getErrors());
551-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
552-
$this->assertContains($sloUrl, $targetUrl);
562+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
563+
$this->assertContains($sloResponseUrl, $targetUrl);
553564
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
554565
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
555566
}
@@ -570,8 +581,8 @@ public function testProcessSLORequestInvalidValid()
570581
$parsedQuery = getParamsFromUrl($targetUrl);
571582

572583
$this->assertEmpty($this->_auth->getErrors());
573-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
574-
$this->assertContains($sloUrl, $targetUrl);
584+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
585+
$this->assertContains($sloResponseUrl, $targetUrl);
575586
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
576587
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
577588
}
@@ -636,8 +647,8 @@ public function testProcessSLORequestDeletingSession()
636647
$targetUrl = getUrlFromRedirect($trace);
637648
$parsedQuery = getParamsFromUrl($targetUrl);
638649

639-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
640-
$this->assertContains($sloUrl, $targetUrl);
650+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
651+
$this->assertContains($sloResponseUrl, $targetUrl);
641652
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
642653
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
643654

@@ -657,8 +668,8 @@ public function testProcessSLORequestDeletingSession()
657668
$targetUrl = getUrlFromRedirect($trace);
658669
$parsedQuery = getParamsFromUrl($targetUrl);
659670

660-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
661-
$this->assertContains($sloUrl, $targetUrl);
671+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
672+
$this->assertContains($sloResponseUrl, $targetUrl);
662673
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
663674
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
664675

tests/src/OneLogin/Saml2/IdPMetadataParserTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public function testParseFileXML()
2121
),
2222
'singleLogoutService' => array (
2323
'url' => 'https://example.onelogin.com/trust/saml2/http-redirect/slo/645460',
24+
'responseUrl' => '',
2425
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
2526
),
2627
'x509cert' => 'MIIEZTCCA02gAwIBAgIUPyy/A3bZAZ4m28PzEUUoT7RJhxIwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UEBhMCVVMxKzApBgNVBAoMIk9uZUxvZ2luIFRlc3QgKHNnYXJjaWEtdXMtcHJlcHJvZCkxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4OTE0NjAeFw0xNjA4MDQyMjI5MzdaFw0yMTA4MDUyMjI5MzdaMHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDN6iqQGcLOCglNO42I2rkzE05UXSiMXT6c8ALThMMiaDw6qqzo3sd/tKK+NcNKWLIIC8TozWVyh5ykUiVZps+08xil7VsTU7E+wKu3kvmOsvw2wlRwtnoKZJwYhnr+RkBa+h1r3ZYUgXm1ZPeHMKj1g18KaWz9+MxYL6BhKqrOzfW/P2xxVRcFH7/pq+ZsDdgNzD2GD+apzY4MZyZj/N6BpBWJ0GlFsmtBegpbX3LBitJuFkk5L4/U/jjF1AJa3boBdCUVfATqO5G03H4XS1GySjBIRQXmlUF52rLjg6xCgWJ30/+t1X+IHLJeixiQ0vxyh6C4/usCEt94cgD1r8ADAgMBAAGjgfIwge8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPW0DcH0G3IwynWgi74co4wZ6n7gwga8GA1UdIwSBpzCBpIAUPW0DcH0G3IwynWgi74co4wZ6n7ihdqR0MHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDaCFD8svwN22QGeJtvD8xFFKE+0SYcSMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAQhB4q9jrycwbHrDSoYR1X4LFFzvJ9Us75wQquRHXpdyS9D6HUBXMGI6ahPicXCQrfLgN8vzMIiqZqfySXXv/8/dxe/X4UsWLYKYJHDJmxXD5EmWTa65chjkeP1oJAc8f3CKCpcP2lOBTthbnk2fEVAeLHR4xNdQO0VvGXWO9BliYPpkYqUIBvlm+Fg9mF7AM/Uagq2503XXIE1Lq//HON68P10vNMwLSKOtYLsoTiCnuIKGJqG37MsZVjQ1ZPRcO+LSLkq0i91gFxrOrVCrgztX4JQi5XkvEsYZGIXXjwHqxTVyt3adZWQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw=='
@@ -70,6 +71,7 @@ public function testParseXML()
7071
),
7172
'singleLogoutService' => array (
7273
'url' => 'https://idp.examle.com/saml/slo',
74+
'responseUrl' => 'https://idp.examle.com/saml/slr',
7375
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
7476
),
7577
'x509certMulti' => array (
@@ -180,6 +182,7 @@ public function testParseDesiredBindingAll()
180182
),
181183
"singleLogoutService" => array(
182184
"url" => "http://idp.example.com/logout",
185+
'responseUrl' => '',
183186
"binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
184187
)
185188
)
@@ -297,6 +300,7 @@ public function testParseMultiCerts()
297300
"idp" => array(
298301
"singleLogoutService" => array(
299302
"url" => "https://idp.examle.com/saml/slo",
303+
'responseUrl' => '',
300304
"binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
301305
),
302306
"x509certMulti" => array(
@@ -336,6 +340,7 @@ public function testParseMultiSigningCerts()
336340
"idp" => array(
337341
"singleLogoutService" => array(
338342
"url" => "https://idp.examle.com/saml/slo",
343+
'responseUrl' => '',
339344
"binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
340345
),
341346
"x509certMulti" => array(
@@ -435,6 +440,7 @@ public function testInjectIntoSettings()
435440
),
436441
'singleLogoutService' => array (
437442
'url' => 'https://idp.adfs.example.com/adfs/ls/',
443+
'responseUrl' => '',
438444
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
439445
),
440446
'x509certMulti' => array (

tests/src/OneLogin/Saml2/SettingsTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ public function testCheckSettings()
333333
$settingsInfo['idp']['entityID'] = 'entityId';
334334
$settingsInfo['idp']['singleSignOnService']['url'] = 'invalid_value';
335335
$settingsInfo['idp']['singleLogoutService']['url'] = 'invalid_value';
336+
$settingsInfo['idp']['singleLogoutService']['responseUrl'] = 'invalid_value';
336337
$settingsInfo['sp']['assertionConsumerService']['url'] = 'invalid_value';
337338
$settingsInfo['sp']['singleLogoutService']['url'] = 'invalid_value';
338339
try {
@@ -341,6 +342,7 @@ public function testCheckSettings()
341342
} catch (OneLogin_Saml2_error $e) {
342343
$this->assertContains('idp_sso_url_invalid', $e->getMessage());
343344
$this->assertContains('idp_slo_url_invalid', $e->getMessage());
345+
$this->assertContains('idp_slo_response_url_invalid', $e->getMessage());
344346
$this->assertContains('sp_acs_url_invalid', $e->getMessage());
345347
$this->assertContains('sp_sls_url_invalid', $e->getMessage());
346348
}

0 commit comments

Comments
 (0)