diff --git a/modules/saml2/www/sp/logout.php b/modules/saml2/www/sp/logout.php
new file mode 100644
index 0000000000000000000000000000000000000000..75d0fa413e7793aee6c1c0a4cb2fca34fd260704
--- /dev/null
+++ b/modules/saml2/www/sp/logout.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * Logout endpoint handler for SAML 2.0 SP authentication client.
+ *
+ * This endpoint handles both logout requests and logout responses.
+ */
+
+if (!array_key_exists('PATH_INFO', $_SERVER)) {
+	throw new SimpleSAML_Error_BadRequest('Missing authentication source id in logout URL');
+}
+
+$sourceId = substr($_SERVER['PATH_INFO'], 1);
+
+$source = SimpleSAML_Auth_Source::getById($sourceId);
+if ($source === NULL) {
+	throw new Exception('Could not find authentication source with id ' . $sourceId);
+}
+
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+
+if (array_key_exists('SAMLResponse', $_GET)) {
+
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	$response = $binding->decodeLogoutResponse($_GET);
+
+	if ($binding->validateQuery($response->getIssuer(), 'SP', 'SAMLResponse')) {
+		SimpleSAML_Logger::debug('module/saml2/sp/logout: Valid signature found on response');
+	}
+
+	if (!array_key_exists('RelayState', $_REQUEST)) {
+		throw new SimpleSAML_Error_BadRequest('Missing RelayState in logout response.');
+	}
+
+	$stateId = $_REQUEST['RelayState'];
+	$state = SimpleSAML_Auth_State::loadState($_REQUEST['RelayState'], sspmod_saml2_Auth_Source_SP::STAGE_LOGOUTSENT);
+
+
+	SimpleSAML_Auth_Source::completeLogout($state);
+
+} elseif (array_key_exists('SAMLRequest', $_GET)) {
+
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+
+	$request = $binding->decodeLogoutRequest($_GET);
+
+	$requestId = $request->getRequestID();
+	$idpEntityId = $request->getIssuer();
+	$relayState = $request->getRelayState();
+
+	if ($binding->validateQuery($idpEntityId, 'SP')) {
+		SimpleSAML_Logger::debug('module/saml2/sp/logout: Valid signature found on request');
+	}
+
+
+	$spEntityId = $source->getEntityId();
+
+	SimpleSAML_Logger::debug('module/saml2/sp/logout: Request from ' . $idpEntityId . ' with request id ' . $requestId);
+	SimpleSAML_Logger::stats('saml20-idp-SLO idpinit ' . $spEntityId . ' ' . $idpEntityId);
+
+	/* Notify source of logout, so that it may call logout callbacks. */
+	$source->onLogout($idpEntityId);
+
+	/* Create an send response. */
+	$lr = new SimpleSAML_XML_SAML20_LogoutResponse($config, $metadata);
+	$responseXML = $lr->generate($spEntityId, $idpEntityId, $requestId, 'SP');
+	$binding->sendMessage($responseXML, $spEntityId, $idpEntityId, $relayState, 'SingleLogoutServiceResponse', 'SAMLResponse');
+
+} else {
+	throw new SimpleSAML_Error_BadRequest('Missing request or response to logout endpoint');
+}