diff --git a/config-templates/config.php b/config-templates/config.php
index 2fb856d782ddd5238d621aaeb28be673ca5c403c..4e0ca044c7a152d26f6ae530011d5292e7e1bee6 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -126,6 +126,7 @@ $config = array (
 	 */
 	'enable.saml20-idp'		=> false,
 	'enable.shib13-idp'		=> false,
+	'enable.adfs-idp'		=> false,
 	'enable.wsfed-sp'		=> false,
 	'enable.authmemcookie' => false,
 
diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index 0009af754272ec872d9983c453de887ada594a2f..b7ab3bc1a270f88f2d1727c527a188c89f0bd6a8 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -57,6 +57,11 @@ class SimpleSAML_IdP {
 				throw new SimpleSAML_Error_Exception('enable.shib13-idp disabled in config.php.');
 			}
 			$this->config = $metadata->getMetaDataConfig(substr($id, 6), 'shib13-idp-hosted');
+		} elseif (substr($id, 0, 5) === 'adfs:') {
+			if (!$globalConfig->getBoolean('enable.adfs-idp', FALSE)) {
+				throw new SimpleSAML_Error_Exception('enable.adfs-idp disabled in config.php.');
+			}
+			$this->config = $metadata->getMetaDataConfig(substr($id, 5), 'adfs-idp-hosted');
 		} else {
 			assert(FALSE);
 		}
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
index 2fbc6ca72362f3847e6aee7846ce41a5a2bf27ba..64f4624480505dff8c8b453e85dc79308d791470 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
@@ -130,6 +130,8 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerFlatFile extends SimpleSAML_Meta
 			return $baseurl . 'shib13/sp/metadata.php';
 		} elseif($set === 'wsfed-sp-hosted') {
 			return 'urn:federation:' . SimpleSAML_Utilities::getSelfHost();
+		} elseif($set === 'adfs-idp-hosted') {
+			return 'urn:federation:' . SimpleSAML_Utilities::getSelfHost() . ':idp';
 		} else {
 			throw new Exception('Can not generate dynamic EntityID for metadata of this type: [' . $set . ']');
 		}
diff --git a/metadata-templates/adfs-idp-hosted.php b/metadata-templates/adfs-idp-hosted.php
new file mode 100644
index 0000000000000000000000000000000000000000..040a199aa2665faa7ebb0f5e5f6c315d5d1cdb96
--- /dev/null
+++ b/metadata-templates/adfs-idp-hosted.php
@@ -0,0 +1,10 @@
+<?php
+
+$metadata['__DYNAMIC:1__'] = array(
+	'host' => '__DEFAULT__',
+	'privatekey' => 'server.pem',
+	'certificate' => 'server.crt',
+	'auth' => 'example-userpass',
+);
+
+?>
diff --git a/metadata-templates/adfs-sp-remote.php b/metadata-templates/adfs-sp-remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..373a6689f58f360984df0cee71a95e90284bcb1f
--- /dev/null
+++ b/metadata-templates/adfs-sp-remote.php
@@ -0,0 +1,14 @@
+<?php
+
+$metadata['urn:federation:localhost'] = array(
+	'prp' => 'https://localhost/adfs/ls/',
+	'simplesaml.nameidattribute' => 'uid',
+	'authproc' => array(
+		50 => array(
+			'class' => 'core:AttributeLimit',
+			'cn', 'mail', 'uid', 'eduPersonAffiliation',
+		),
+	),
+);
+
+?>
diff --git a/modules/adfs/lib/IdP/ADFS.php b/modules/adfs/lib/IdP/ADFS.php
new file mode 100644
index 0000000000000000000000000000000000000000..da55aa28a832d52f50db049250e192f1cc00c887
--- /dev/null
+++ b/modules/adfs/lib/IdP/ADFS.php
@@ -0,0 +1,199 @@
+<?php
+
+class sspmod_adfs_IdP_ADFS {
+
+	public static function receiveAuthnRequest(SimpleSAML_IdP $idp) {
+		try {
+			// accomodate for disfunctional $_GET "windows" slash decoding in PHP
+			$wctx = $_GET['wctx'];
+			foreach (explode('&', $_SERVER['REQUEST_URI']) as $e) {
+				$a = explode('=', $e);
+				if ($a[0] == 'wctx') $wctx = urldecode($a[1]);
+			}
+			$requestid = $wctx;
+			$issuer = $_GET['wtrealm'];
+			$requestcache = array(
+				'RequestID' => $requestid,
+				'Issuer' => $issuer,
+				'RelayState' => $requestid
+			);
+
+			$spEntityId = $requestcache['Issuer'];
+			$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+			$spMetadata = $metadata->getMetaDataConfig($spEntityId, 'adfs-sp-remote');
+			
+			SimpleSAML_Logger::info('ADFS - IdP.prp: Incoming Authentication request: '.$issuer.' id '.$requestid);
+	
+		} catch(Exception $exception) {
+			SimpleSAML_Utilities::fatalError($session->getTrackID(), 'PROCESSAUTHNREQUEST', $exception);
+		}
+		
+		$sessionLostURL = NULL; // TODO?
+		$forceAuthn = FALSE;
+		$isPassive = FALSE;
+
+		$state = array(
+			'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendResponse'),
+//			SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC => array('sspmod_adfs_IdP', 'handleAuthError'),
+//			SimpleSAML_Auth_State::RESTART => $sessionLostURL,
+			'SPMetadata' => $spMetadata->toArray(),
+			'ForceAuthn' => $forceAuthn,
+			'isPassive' => $isPassive,
+			'adfs:wctx' => $wctx,
+		);
+
+		$idp->handleAuthenticationRequest($state);		
+	}
+
+	public static function ADFS_GenerateResponse($issuer, $target, $nameid, $attributes) {
+		#$nameid = 'hans@surfnet.nl';
+		$issueInstant = SimpleSAML_Utilities::generateTimestamp();
+		$notBefore = SimpleSAML_Utilities::generateTimestamp(time() - 30);
+		$assertionExpire = SimpleSAML_Utilities::generateTimestamp(time() + 60 * 5);
+		$assertionID = SimpleSAML_Utilities::generateID();
+		$nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
+		$result =
+'<wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
+   <wst:RequestedSecurityToken>
+     <saml:Assertion Issuer="' . $issuer . '" IssueInstant="' . $issueInstant . '" AssertionID="' . $assertionID . '" MinorVersion="1" MajorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
+       <saml:Conditions NotOnOrAfter="' . $assertionExpire . '" NotBefore="' . $notBefore . '">
+         <saml:AudienceRestrictionCondition>
+           <saml:Audience>' . $target .'</saml:Audience>
+         </saml:AudienceRestrictionCondition>
+       </saml:Conditions>
+       <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified" AuthenticationInstant="' . $issueInstant . '">
+         <saml:Subject>
+           <saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
+         </saml:Subject>
+       </saml:AuthenticationStatement>
+       <saml:AttributeStatement>
+         <saml:Subject>
+           <saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
+         </saml:Subject>';
+		foreach ($attributes as $name => $values) {
+			if ((!is_array($values)) || (count($values) == 0)) continue;
+			$hasValue = FALSE;
+			$r = '<saml:Attribute AttributeNamespace="http://schemas.xmlsoap.org/claims" AttributeName="' . htmlspecialchars($name) .'">';
+			foreach ($values as $value) {
+				if ( (!isset($value)) or ($value === '')) continue;
+				$r .= '<saml:AttributeValue>' . htmlspecialchars($value) . '</saml:AttributeValue>';
+				$hasValue = TRUE;
+			}
+			$r .= '</saml:Attribute>';
+			if ($hasValue) $result .= $r;
+		}
+		$result .= '
+       </saml:AttributeStatement>
+     </saml:Assertion>
+   </wst:RequestedSecurityToken>
+   <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
+     <wsa:Address>' . $target . '</wsa:Address>
+   </wsa:EndpointReference></wsp:AppliesTo>
+ </wst:RequestSecurityTokenResponse>';
+		return $result;
+	}
+
+	public static function ADFS_SignResponse($response, $key, $cert) {
+		$objXMLSecDSig = new XMLSecurityDSig();
+		$objXMLSecDSig->idKeys = array('AssertionID');	
+		$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);	
+		$responsedom = new DOMDocument();
+		$responsedom->loadXML(str_replace ("\r", "", $response));
+		$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
+		$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1,
+			array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
+			array('id_name' => 'AssertionID'));
+		$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
+		$objKey->loadKey($key, TRUE);
+		$objXMLSecDSig->sign($objKey);
+		if ($cert) {
+			$public_cert = file_get_contents($cert);
+			$objXMLSecDSig->add509Cert($public_cert, TRUE);
+		}
+		$newSig = $responsedom->importNode($objXMLSecDSig->sigNode, TRUE);
+		$firstassertionroot->appendChild($newSig);	
+		return $responsedom->saveXML();
+	}
+
+	public static function ADFS_PostResponse($url, $wresult, $wctx) {
+		print '
+<body onload="document.forms[0].submit()"><form method="post" action="' . $url . '">
+	<input type="hidden" name="wa" value="wsignin1.0">
+	<input type="hidden" name="wresult" value="' . htmlspecialchars($wresult) . '">
+	<input type="hidden" name="wctx" value="' . htmlspecialchars($wctx) . '">
+	<noscript><input type="submit" value="Continue"></noscript>
+</form></body>';
+		exit;
+	}
+
+	public static function sendResponse(array $state) {
+		$spMetadata = $state["SPMetadata"];
+		$spEntityId = $spMetadata['entityid'];
+		$spMetadata = SimpleSAML_Configuration::loadFromArray($spMetadata,
+			'$metadata[' . var_export($spEntityId, TRUE) . ']');
+
+		$attributes = $state['Attributes'];
+		
+		$nameidattribute = $spMetadata->getValue('simplesaml.nameidattribute');
+		if (!empty($nameidattribute)) {
+			if (!array_key_exists($nameidattribute, $attributes)) {
+				throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set');
+			}
+			$nameid = $attributes[$nameidattribute][0];
+		} else {
+			$nameid = SimpleSAML_Utilities::generateID();
+		}
+
+		$idp = SimpleSAML_IdP::getByState($state);		
+		$idpMetadata = $idp->getConfig();
+		$idpEntityId = $idpMetadata->getString('entityid');
+		
+		$idp->addAssociation(array(
+			'id' => 'adfs:' . $spEntityId,
+			'Handler' => 'sspmod_adfs_IdP_ADFS',
+			'adfs:entityID' => $spEntityId,
+		));
+		
+		$response = sspmod_adfs_IdP_ADFS::ADFS_GenerateResponse($idpEntityId, $spEntityId, $nameid, $attributes);
+
+		$config = SimpleSAML_Configuration::getInstance();
+		$certdir = $config->getPathValue('certdir', 'cert/');		
+		$wresult = sspmod_adfs_IdP_ADFS::ADFS_SignResponse($response, $certdir . $idpMetadata->getString('privatekey'), $certdir . $idpMetadata->getString('certificate'));
+
+		$wctx = $state['adfs:wctx'];
+		sspmod_adfs_IdP_ADFS::ADFS_PostResponse($spMetadata->getValue('prp'), $wresult, $wctx);
+	}
+/*
+	public static function handleAuthError(SimpleSAML_Error_Exception $exception, array $state) {
+	}
+*/
+	public static function sendLogoutResponse(SimpleSAML_IdP $idp, array $state) {
+		// NB:: we don't know from which SP the logout request came from
+		$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+		$idpMetadata = $idp->getConfig();
+		SimpleSAML_Utilities::redirect($idpMetadata->getValue('redirect-after-logout', SimpleSAML_Utilities::getBaseURL()));
+	}
+	
+	public static function receiveLogoutMessage(SimpleSAML_IdP $idp) {
+		$state = array(
+			'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendLogoutResponse'),
+		);
+		//$spEntityId = NULL;
+		//$assocId = 'adfs:' . $spEntityId;
+		$assocId = NULL;
+		// TODO: verify that this is really no problem for: 
+		//       a) SSP, because there's no caller SP...
+		//       b) ADFS SP because caller will be called back...
+		$idp->handleLogoutRequest($state, $assocId);
+	}
+
+	// accepts an association array, and returns an URL that can be accessed to terminate the association.
+	public static function getLogoutURL(SimpleSAML_IdP $idp, array $association, $relayState) {
+		$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+		$idpMetadata = $idp->getConfig();
+		$spMetadata = $metadata->getMetaDataConfig($association['adfs:entityID'], 'adfs-sp-remote');
+		// 'https://adfs-test.showcase.surfnet.nl/adfs/ls/?wa=wsignoutcleanup1.0&wreply=https%3A%2F%2Flocalhost%2Fsimplesaml');
+		$returnTo = SimpleSAML_Module::getModuleURL('adfs/idp/prp.php?assocId=' . urlencode($association["id"]) . '&relayState=' . urlencode($relayState));
+		return $spMetadata->getValue('prp') . '?' . 'wa=wsignoutcleanup1.0&wreply=' . urlencode($returnTo);
+	}
+}
diff --git a/modules/adfs/www/idp/prp.php b/modules/adfs/www/idp/prp.php
index 3b38ccb448d068440c8930eae3e7223c120d1821..c6f545e33c62745b86b7e1d74996108d1ceee28c 100644
--- a/modules/adfs/www/idp/prp.php
+++ b/modules/adfs/www/idp/prp.php
@@ -2,274 +2,30 @@
 /**
  * ADFS PRP IDP protocol support for simpleSAMLphp.
  *
- * @author Hans Zandbelt, SURFnet BV. <hans.zandbelt@surfnet.nl>
+ * @author Hans Zandbelt, SURFnet bv, <hans.zandbelt@surfnet.nl>
  * @package simpleSAMLphp
  * @version $Id$
  */
 
-$config = SimpleSAML_Configuration::getInstance();
-$adfsconfig = SimpleSAML_Configuration::getConfig('adfs-idp-hosted.php');
-$session = SimpleSAML_Session::getInstance();
+SimpleSAML_Logger::info('ADFS - IdP.prp: Accessing ADFS IdP endpoint prp');
 
-SimpleSAML_Logger::info('ADFS - IdP.SSOService: Accessing ADFS IdP endpoint SSOService');
-
-try {
-	if (array_key_exists('entityId', $config)) {
-		$idpentityid = $config['entityId'];
-	} else {
-		$idpentityid = 'urn:federation:' . SimpleSAML_Utilities::getSelfHost() . ':idp';
-	}
-} catch (Exception $exception) {
-	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
-}
-
-SimpleSAML_Logger::info('ADFS - IdP.SSOService: Accessing ADFS IdP endpoint SSOService');
-
-function ADFS_GenerateResponse($issuer, $target, $nameid, $attributes) {
-#	$nameid = 'hans@surfnet.nl';
-	$issueInstant = SimpleSAML_Utilities::generateTimestamp();
-	$notBefore = SimpleSAML_Utilities::generateTimestamp(time() - 30);
-	$assertionExpire = SimpleSAML_Utilities::generateTimestamp(time() + 60 * 5);
-	$assertionID = SimpleSAML_Utilities::generateID();
-	$nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
-	$result =
-'<wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
-   <wst:RequestedSecurityToken>
-     <saml:Assertion Issuer="' . $issuer . '" IssueInstant="' . $issueInstant . '" AssertionID="' . $assertionID . '" MinorVersion="1" MajorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
-       <saml:Conditions NotOnOrAfter="' . $assertionExpire . '" NotBefore="' . $notBefore . '">
-         <saml:AudienceRestrictionCondition>
-           <saml:Audience>' . $target .'</saml:Audience>
-         </saml:AudienceRestrictionCondition>
-       </saml:Conditions>
-       <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified" AuthenticationInstant="' . $issueInstant . '">
-         <saml:Subject>
-           <saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
-         </saml:Subject>
-       </saml:AuthenticationStatement>
-       <saml:AttributeStatement>
-         <saml:Subject>
-           <saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
-         </saml:Subject>';
-	foreach ($attributes as $name => $values) {
-		if ((!is_array($values)) || (count($values) == 0)) continue;
-		$hasValue = FALSE;
-		$r = '<saml:Attribute AttributeNamespace="http://schemas.xmlsoap.org/claims" AttributeName="' . htmlspecialchars($name) .'">';
-		foreach ($values as $value) {
-			if ( (!isset($value)) or ($value === '')) continue;
-			$r .= '<saml:AttributeValue>' . htmlspecialchars($value) . '</saml:AttributeValue>';
-			$hasValue = TRUE;
-		}
-		$r .= '</saml:Attribute>';
-		if ($hasValue) $result .= $r;
-	}
-	$result .= '
-       </saml:AttributeStatement>
-     </saml:Assertion>
-   </wst:RequestedSecurityToken>
-   <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
-     <wsa:Address>' . $target . '</wsa:Address>
-   </wsa:EndpointReference></wsp:AppliesTo>
- </wst:RequestSecurityTokenResponse>';
-	return $result;
-}
-
-function ADFS_SignResponse($response, $key, $cert) {
-	$objXMLSecDSig = new XMLSecurityDSig();
-	$objXMLSecDSig->idKeys = array('AssertionID');	
-	$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);	
-	$responsedom = new DOMDocument();
-	$responsedom->loadXML(str_replace ("\r", "", $response));
-	$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
-	$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1,
-		array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
-		array('id_name' => 'AssertionID'));
-	$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
-	$objKey->loadKey($key, TRUE);
-	$objXMLSecDSig->sign($objKey);
-	if ($cert) {
-		$public_cert = file_get_contents($cert);
-		$objXMLSecDSig->add509Cert($public_cert, TRUE);
-	}
-	$newSig = $responsedom->importNode($objXMLSecDSig->sigNode, TRUE);
-	$firstassertionroot->appendChild($newSig);	
-	return $responsedom->saveXML();
-}
-
-function ADFS_PostResponse($url, $wresult, $wctx) {
-	print '
-<body onload="document.forms[0].submit()"><form method="post" action="' . $url . '">
-	<input type="hidden" name="wa" value="wsignin1.0">
-	<input type="hidden" name="wresult" value="' . htmlspecialchars($wresult) . '">
-	<input type="hidden" name="wctx" value="' . htmlspecialchars($wctx) . '">
-	<noscript><input type="submit" value="Continue"></noscript>
-</form></body>';
-	exit;
-}
+$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+$idpEntityId = $metadata->getMetaDataCurrentEntityID('adfs-idp-hosted');
+$idp = SimpleSAML_IdP::getById('adfs:' . $idpEntityId);
 
 if (isset($_GET['wa'])) {
-
-	if ($_GET['wa'] == 'wsignin1.0') {
-		try {
-			// accomodate for disfunctional $_GET "windows" slash decoding in PHP
-			$wctx = $_GET['wctx'];
-			foreach (explode('&', $_SERVER['REQUEST_URI']) as $e) {
-				$a = explode('=', $e);
-				if ($a[0] == 'wctx') $wctx = urldecode($a[1]);
-			}
-			$requestid = $wctx;
-			$issuer = $_GET['wtrealm'];
-			$requestcache = array(
-				'RequestID' => $requestid,
-				'Issuer' => $issuer,
-				'RelayState' => $requestid
-			);
-
-			$spentityid = $requestcache['Issuer'];
-		
-			SimpleSAML_Logger::info('ADFS - IdP.SSOService: Incoming Authentication request: '.$issuer.' id '.$requestid);
-	
-		} catch(Exception $exception) {
-			SimpleSAML_Utilities::fatalError($session->getTrackID(), 'PROCESSAUTHNREQUEST', $exception);
-		}
-	}
-
-} elseif(isset($_GET['RequestID'])) {
-
-	try {
-	
-		SimpleSAML_Logger::info('ADFS - IdP.SSOService: Got incoming authentication ID');
-		
-		$authId = $_GET['RequestID'];
-		$requestcache = $session->getAuthnRequest('adfs', $authId);
-		if (!$requestcache) {
-			throw new Exception('Could not retrieve cached RequestID = ' . $authId);
-		}
-		
-	} catch(Exception $exception) {
-		SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CACHEAUTHNREQUEST', $exception);
-	}
-	
-} elseif(isset($_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM])) {
-
-	$authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
-	$authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
-	$requestcache = $authProcState['core:adfs-idp:requestcache'];
-
-} else {
-	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SSOSERVICEPARAMS');
-}
-
-if(SimpleSAML_Auth_Source::getById($adfsconfig->getValue('auth')) !== NULL) {
-	$authSource = TRUE;
-	$authority = $adfsconfig->getValue('auth');
-} else {
-	$authSource = FALSE;
-	$authority = $adfsconfig->getValue('authority');
-}
-
-if (!$session->isValid($authority) ) {
-
-	SimpleSAML_Logger::info('ADFS - IdP.SSOService: Will go to authentication module ' . $adfsconfig->getValue('auth'));
-
-	$authId = SimpleSAML_Utilities::generateID();
-	$session->setAuthnRequest('adfs', $authId, $requestcache);
-
-	$redirectTo = SimpleSAML_Utilities::selfURLNoQuery() . '?RequestID=' . urlencode($authId);
-
-	if($authSource) {
-
-		SimpleSAML_Auth_Default::initLogin($adfsconfig->getValue('auth'), $redirectTo);
-	} else {
-		$authurl = '/' . $config->getBaseURL() . $adfsconfig->getValue('auth');
-
-		SimpleSAML_Utilities::redirect($authurl, array(
-		       'RelayState' => $redirectTo,
-		       'AuthId' => $authId,
-		       'protocol' => 'adfs',
-		));
-	}
-
-} else {
-
-	try {
-	
-		$spentityid = $requestcache['Issuer'];
-		$spmetadata = SimpleSAML_Configuration::getConfig('adfs-sp-remote.php');
-		
-		$arr = $spmetadata->getValue($spentityid);
-		if (!isset($arr)) {
-			throw new Exception('Metadata for ADFS SP "' . $spentityid . '" could not be found in adfs-sp-remote.php!');
-		}
-		$spmetadata = SimpleSAML_Configuration::loadFromArray($arr);
-
-		SimpleSAML_Logger::info('ADFS - IdP.SSOService: Sending back AuthnResponse to ' . $spentityid);
-		
-		$attributes = $session->getAttributes();
-		
-		if (!isset($authProcState)) {
-
-			$idpap = $adfsconfig->getValue('authproc');
-			if ($idpap) $idpap = array('authproc' => $idpap); else $idpap = array();
-			$idpap['entityid'] = $idpentityid;
-			
-			$spap = $spmetadata->getValue('authproc');
-			if ($spap) $spap = array('authproc' => $spap); else $spap = array();
-			$spap['entityid'] = $spentityid;
-			
-			$pc = new SimpleSAML_Auth_ProcessingChain($idpap, $spap, 'idp');
-
-			$authProcState = array(
-				'core:adfs-idp:requestcache' => $requestcache,
-				'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
-				'Attributes' => $attributes,
-				'Destination' => $spap,
-				'Source' => $idpap,
-				'isPassive' => false,
-			);
-
-			$previousSSOTime = $session->getData('adfs-idp-ssotime', $spentityid);
-			if ($previousSSOTime !== NULL) {
-				$authProcState['PreviousSSOTimestamp'] = $previousSSOTime;
-			}
-
-			try {
-				$pc->processState($authProcState);
-			} catch (SimpleSAML_Error_NoPassive $e) {
-				SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $exception);
-			}
-
-			$requestcache['AuthProcState'] = $authProcState;
-		}
-
-		$attributes = $authProcState['Attributes'];
-
-		$session->setData('adfs-idp-ssotime', $spentityid, time(),
-			SimpleSAML_Session::DATA_TIMEOUT_LOGOUT);
-
-		$requestID = NULL; $relayState = NULL;
-		if (array_key_exists('RequestID', $requestcache)) $requestID = $requestcache['RequestID'];
-		if (array_key_exists('RelayState', $requestcache)) $relayState = $requestcache['RelayState'];
-
-		$nameid = $session->getNameID();
-		$nameid = $nameid['Value'];
-		
-		$nameidattribute = $spmetadata->getValue('simplesaml.nameidattribute');
-		if (isset($nameidattribute)) {
-			if (!array_key_exists($nameidattribute, $attributes)) {
-				throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set');
-			}
-			$nameid = $attributes[$nameidattribute][0];
-		}
-
-		$response = ADFS_GenerateResponse($idpentityid, $spentityid, $nameid, $attributes);
-		$wresult = ADFS_SignResponse($response, $config->getPathValue('certdir', 'cert/') . $adfsconfig->getValue('key'), $config->getPathValue('certdir', 'cert/') . $adfsconfig->getValue('cert'));
-
-		ADFS_PostResponse($spmetadata->getValue('prp'), $wresult, $relayState);
-		
-	} catch(Exception $exception) {
-		SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $exception);
+	if ($_GET['wa'] === 'wsignout1.0') {
+		sspmod_adfs_IdP_ADFS::receiveLogoutMessage($idp);
+	} else if ($_GET['wa'] === 'wsignin1.0') {
+		sspmod_adfs_IdP_ADFS::receiveAuthnRequest($idp);
 	}
-	
+	assert('FALSE');		
+} elseif(isset($_GET['assocId'])) {
+	// logout response from ADFS SP
+	$assocId = $_GET['assocId']; /* Association ID of the SP that sent the logout response. */
+	$relayState = $_GET['relayState']; /* Data that was sent in the logout request to the SP. Can be null. */
+	$logoutError = NULL; /* NULL on success, or an instance of a SimpleSAML_Error_Exception on failure. */
+	$idp->handleLogoutResponse($assocId, $relayState, $logoutError);
 }
 
 ?>