public function SamlService::sls in SAML Authentication 4.x
Same name and namespace in other branches
- 8.3 src/SamlService.php \Drupal\samlauth\SamlService::sls()
- 8.2 src/SamlService.php \Drupal\samlauth\SamlService::sls()
Does processing for the Single Logout Service.
Return value
null|string Usually returns nothing. May return a URL to redirect to.
File
- src/
SamlService.php, line 653
Class
- SamlService
- Governs communication between the SAML toolkit and the IdP / login behavior.
Namespace
Drupal\samlauthCode
public function sls() {
$config = $this->configFactory
->get('samlauth.authentication');
// We might at some point check if this code can be abstracted a bit...
if ($config
->get('debug_log_in')) {
if (isset($_GET['SAMLResponse'])) {
$response = base64_decode($_GET['SAMLResponse']);
if ($response) {
$this->logger
->debug("SLS received 'SAMLResponse' in GET request (base64 decoded): <pre>@message</pre>", [
'@message' => $response,
]);
}
else {
$this->logger
->warning("SLS received 'SAMLResponse' in GET request which could not be base64 decoded: <pre>@message</pre>", [
'@message' => $_POST['SAMLResponse'],
]);
}
}
elseif (isset($_GET['SAMLRequest'])) {
$response = base64_decode($_GET['SAMLRequest']);
if ($response) {
$this->logger
->debug("SLS received 'SAMLRequest' in GET request (base64 decoded): <pre>@message</pre>", [
'@message' => $response,
]);
}
else {
$this->logger
->warning("SLS received 'SAMLRequest' in GET request which could not be base64 decoded: <pre>@message</pre>", [
'@message' => $_POST['SAMLRequest'],
]);
}
}
else {
// Not sure if we should be more detailed...
$this->logger
->warning("HTTP request to SLS is not a GET request, or contains no 'SAMLResponse'/'SAMLRequest' parameters.");
}
}
// Perform flood control; see acs().
$flood_config = $this->configFactory
->get('user.flood');
if (!$this->flood
->isAllowed('samlauth.failed_logout_ip', $flood_config
->get('ip_limit'), $flood_config
->get('ip_window'))) {
throw new TooManyRequestsHttpException(NULL, 'Access is blocked because of IP based flood prevention.');
}
try {
// This line means we're extracting logic previously encapsulated inside
// the Auth class. That's slightly unfortunate but doesn't compare to all
// other considerations still needing to be made re. refactoring logic.
$purpose = isset($_GET['SAMLResponse']) ? 'sls-response' : 'sls-request';
// Unlike the 'logout()' route, we only log the user out if we have a
// valid request/response, so first have the SAML Toolkit check things.
// Don't have it do any session actions, because nothing is needed
// besides our own logout actions (if any). This call can either set an
// error condition or throw a \OneLogin_Saml2_Error, depending on whether
// we are processing a POST request; don't catch anything.
// @todo should we check a LogoutResponse against the ID of the
// LogoutRequest we sent earlier? Seems to be not absolutely required on
// top of the validity / signature checks which the library already does
// - but every extra check is good. Maybe make it optional.
$url = $this
->getSamlAuth($purpose)
->processSLO(TRUE, NULL, (bool) $config
->get('security_logout_reuse_sigs'), NULL, TRUE);
} catch (\Exception $e) {
$this->flood
->register('samlauth.failed_logout_ip', $flood_config
->get('ip_window'));
throw $e;
}
if ($config
->get('debug_log_saml_in')) {
// There should be no way we can get here if neither GET parameter is set;
// if nothing gets logged, that's a bug.
if (isset($_GET['SAMLResponse'])) {
$this->logger
->debug('SLS received SAML response: <pre>@message</pre>', [
'@message' => $this
->getSamlAuth($purpose)
->getLastResponseXML(),
]);
}
elseif (isset($_GET['SAMLRequest'])) {
$this->logger
->debug('SLS received SAML request: <pre>@message</pre>', [
'@message' => $this
->getSamlAuth($purpose)
->getLastRequestXML(),
]);
}
}
// Now look if there were any errors and also throw.
$errors = $this
->getSamlAuth($purpose)
->getErrors();
if (!empty($errors)) {
// We have one or multiple error types / short descriptions, and one
// 'reason' for the last error.
throw new \RuntimeException('Error(s) encountered during processing of SLS response. Type(s): ' . implode(', ', array_unique($errors)) . '; reason given for last error: ' . $this
->getSamlAuth($purpose)
->getLastErrorReason());
}
// Remove SAML session data, log the user out of Drupal, and return a
// redirect URL if we got any. Usually,
// - a LogoutRequest means we need to log out and redirect back to the IdP,
// for which the SAML Toolkit returned a URL.
// - after a LogoutResponse we don't need to log out because we already did
// that at the start of the process, in logout() - but there's nothing
// against checking. We did not get an URL returned and our caller can
// decide what to do next.
$this
->drupalLogoutHelper();
return $url;
}