Skip to content

Commit f04314e

Browse files
authored
Merge pull request #379 from mwey/feature-slo-logout-response-url-3-1
Feature support: SLO ResponseLocation
2 parents 5d14862 + 7101bdb commit f04314e

10 files changed

Lines changed: 66 additions & 16 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,9 @@ $settings = array(
337337
'singleLogoutService' => array(
338338
// URL Location of the IdP where SLO Request will be sent.
339339
'url' => '',
340+
// URL location of the IdP where SLO Response will be sent (ResponseLocation)
341+
// if not set, url for the SLO Request will be used
342+
'responseUrl' => '',
340343
// SAML protocol binding to be used when returning the <Response>
341344
// message. OneLogin Toolkit supports the HTTP-Redirect binding
342345
// only for this endpoint.

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 SLO Response will be sent (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

src/Saml2/Auth.php

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

325-
return $this->redirectTo($this->getSLOurl(), $parameters, $stay);
325+
return $this->redirectTo($this->getSLOResponseUrl(), $parameters, $stay);
326326
}
327327
} else {
328328
$this->_errors[] = 'invalid_binding';
@@ -633,6 +633,20 @@ public function getSLOurl()
633633
return $url;
634634
}
635635

636+
/**
637+
* Gets the SLO response url.
638+
*
639+
* @return string|null The response url of the Single Logout Service
640+
*/
641+
public function getSLOResponseUrl()
642+
{
643+
$idpData = $this->_settings->getIdPData();
644+
if (isset($idpData['singleLogoutService']) && isset($idpData['singleLogoutService']['responseUrl'])) {
645+
return $idpData['singleLogoutService']['responseUrl'];
646+
}
647+
return $this->getSLOurl();
648+
}
649+
636650
/**
637651
* Gets the ID of the last AuthNRequest or LogoutRequest generated by the Service Provider.
638652
*

src/Saml2/IdPMetadataParser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ public static function parseXML($xml, $entityId = null, $desiredNameIdFormat = n
156156
if ($sloNodes->length > 0) {
157157
$metadataInfo['idp']['singleLogoutService'] = array(
158158
'url' => $sloNodes->item(0)->getAttribute('Location'),
159+
'responseUrl' => $sloNodes->item(0)->getAttribute('ResponseLocation'),
159160
'binding' => $sloNodes->item(0)->getAttribute('Binding')
160161
);
161162
}

src/Saml2/Settings.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,14 @@ public function checkIdPSettings(array $settings)
520520
$errors[] = 'idp_slo_url_invalid';
521521
}
522522

523+
if (isset($idp['singleLogoutService'])
524+
&& isset($idp['singleLogoutService']['responseUrl'])
525+
&& !empty($idp['singleLogoutService']['responseUrl'])
526+
&& !filter_var($idp['singleLogoutService']['responseUrl'], FILTER_VALIDATE_URL)
527+
) {
528+
$errors[] = 'idp_slo_response_url_invalid';
529+
}
530+
523531
if (isset($settings['security'])) {
524532
$security = $settings['security'];
525533

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: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ public function testGetSLOurl()
9292
$this->assertEquals($this->_auth->getSLOurl(), $sloUrl);
9393
}
9494

95+
/**
96+
* Tests the getSLOResponseUrl method of the Auth class
97+
*
98+
* @covers OneLogin\Saml2\Auth::getSLOurl
99+
*/
100+
public function testGetSLOResponseUrl()
101+
{
102+
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
103+
$this->assertEquals($this->_auth->getSLOResponseUrl(), $sloUrl);
104+
}
105+
106+
95107
/**
96108
* Tests the processResponse method of the Auth class
97109
* Case No Response, An exception is throw
@@ -620,8 +632,8 @@ public function testProcessSLORequestInvalidValid()
620632
$parsedQuery = getParamsFromUrl($targetUrl);
621633

622634
$this->assertEmpty($this->_auth->getErrors());
623-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
624-
$this->assertContains($sloUrl, $targetUrl);
635+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
636+
$this->assertContains($sloResponseUrl, $targetUrl);
625637
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
626638
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
627639

@@ -635,8 +647,8 @@ public function testProcessSLORequestInvalidValid()
635647
$parsedQuery = getParamsFromUrl($targetUrl);
636648

637649
$this->assertEmpty($this->_auth->getErrors());
638-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
639-
$this->assertContains($sloUrl, $targetUrl);
650+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
651+
$this->assertContains($sloResponseUrl, $targetUrl);
640652
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
641653
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
642654
}
@@ -704,8 +716,8 @@ public function testProcessSLORequestDeletingSession()
704716
$targetUrl = getUrlFromRedirect($trace);
705717
$parsedQuery = getParamsFromUrl($targetUrl);
706718

707-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
708-
$this->assertContains($sloUrl, $targetUrl);
719+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
720+
$this->assertContains($sloResponseUrl, $targetUrl);
709721
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
710722
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
711723

@@ -725,8 +737,8 @@ public function testProcessSLORequestDeletingSession()
725737
$targetUrl = getUrlFromRedirect($trace);
726738
$parsedQuery = getParamsFromUrl($targetUrl);
727739

728-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
729-
$this->assertContains($sloUrl, $targetUrl);
740+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
741+
$this->assertContains($sloResponseUrl, $targetUrl);
730742
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
731743
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
732744

@@ -778,8 +790,8 @@ public function testProcessSLORequestDeletingSessionCallback()
778790
$targetUrl = getUrlFromRedirect($trace);
779791
$parsedQuery = getParamsFromUrl($targetUrl);
780792

781-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
782-
$this->assertContains($sloUrl, $targetUrl);
793+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];;;
794+
$this->assertContains($sloResponseUrl, $targetUrl);
783795
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
784796
$this->assertArrayNotHasKey('RelayState', $parsedQuery);
785797

@@ -828,8 +840,8 @@ public function testProcessSLORequestRelayState()
828840
$targetUrl = getUrlFromRedirect($trace);
829841
$parsedQuery = getParamsFromUrl($targetUrl);
830842

831-
$sloUrl = $this->_settingsInfo['idp']['singleLogoutService']['url'];
832-
$this->assertContains($sloUrl, $targetUrl);
843+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
844+
$this->assertContains($sloResponseUrl, $targetUrl);
833845
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
834846
$this->assertArrayHasKey('RelayState', $parsedQuery);
835847
$this->assertEquals('http://relaystate.com', $parsedQuery['RelayState']);
@@ -876,8 +888,8 @@ public function testProcessSLORequestSignedResponse()
876888
$targetUrl = getUrlFromRedirect($trace);
877889
$parsedQuery = getParamsFromUrl($targetUrl);
878890

879-
$sloUrl = $settingsInfo['idp']['singleLogoutService']['url'];
880-
$this->assertContains($sloUrl, $targetUrl);
891+
$sloResponseUrl = $this->_settingsInfo['idp']['singleLogoutService']['responseUrl'];
892+
$this->assertContains($sloResponseUrl, $targetUrl);
881893
$this->assertArrayHasKey('SAMLResponse', $parsedQuery);
882894
$this->assertArrayHasKey('RelayState', $parsedQuery);
883895
$this->assertArrayHasKey('SigAlg', $parsedQuery);

tests/src/OneLogin/Saml2/IdPMetadataParserTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function testParseFileXML()
2626
),
2727
'singleLogoutService' => array(
2828
'url' => 'https://example.onelogin.com/trust/saml2/http-redirect/slo/645460',
29+
'responseUrl' => '',
2930
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
3031
),
3132
'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=='
@@ -74,6 +75,7 @@ public function testParseXML()
7475
),
7576
'singleLogoutService' => array(
7677
'url' => 'https://idp.examle.com/saml/slo',
78+
'responseUrl' => 'https://idp.examle.com/saml/slr',
7779
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
7880
),
7981
'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
)
@@ -296,6 +299,7 @@ public function testParseMultiCerts()
296299
"idp" => array(
297300
"singleLogoutService" => array(
298301
"url" => "https://idp.examle.com/saml/slo",
302+
"responseUrl" => "",
299303
"binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
300304
),
301305
"x509certMulti" => array(
@@ -333,6 +337,7 @@ public function testParseMultiSigningCerts()
333337
"idp" => array(
334338
"singleLogoutService" => array(
335339
"url" => "https://idp.examle.com/saml/slo",
340+
"responseUrl" => "",
336341
"binding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
337342
),
338343
"x509certMulti" => array(
@@ -428,6 +433,7 @@ public function testInjectIntoSettings()
428433
),
429434
'singleLogoutService' => array(
430435
'url' => 'https://idp.adfs.example.com/adfs/ls/',
436+
'responseUrl' => '',
431437
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
432438
),
433439
'x509certMulti' => array(

tests/src/OneLogin/Saml2/SettingsTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ public function testCheckSettings()
316316
$settingsInfo['idp']['entityID'] = 'entityId';
317317
$settingsInfo['idp']['singleSignOnService']['url'] = 'invalid_value';
318318
$settingsInfo['idp']['singleLogoutService']['url'] = 'invalid_value';
319+
$settingsInfo['idp']['singleLogoutService']['responseUrl'] = 'invalid_value';
319320
$settingsInfo['sp']['assertionConsumerService']['url'] = 'invalid_value';
320321
$settingsInfo['sp']['singleLogoutService']['url'] = 'invalid_value';
321322
try {
@@ -324,6 +325,7 @@ public function testCheckSettings()
324325
} catch (Error $e) {
325326
$this->assertContains('idp_sso_url_invalid', $e->getMessage());
326327
$this->assertContains('idp_slo_url_invalid', $e->getMessage());
328+
$this->assertContains('idp_slo_response_url_invalid', $e->getMessage());
327329
$this->assertContains('sp_acs_url_invalid', $e->getMessage());
328330
$this->assertContains('sp_sls_url_invalid', $e->getMessage());
329331
}

0 commit comments

Comments
 (0)