diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index 93798dcb1e4e48fb72797f72a27e39044e6cc0a4..136c40da7a0848fd37fd3f3386c937d7314fabdf 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -137,35 +137,28 @@ class SimpleSAML_IdP {
 
 
 	/**
-	 * Retrieve list of SP associations.
+	 * Add an SP association.
 	 *
-	 * @return array  List of SP associations.
+	 * @param array  The SP association.
 	 */
-	public function getAssociations() {
+	public function addAssociation(array $association) {
+		assert('isset($association["id"])');
+		assert('isset($association["Handler"])');
 
 		$session = SimpleSAML_Session::getInstance();
+		$session->addAssociation($this->id, $association);
+	}
 
-		$associations = array();
-
-		foreach ($session->get_sp_list() as $spEntityId) {
-
-			$nameId = $session->getSessionNameId('saml20-sp-remote', $spEntityId);
-			if($nameId === NULL) {
-				$nameId = $this->getNameID();
-			}
-
-			$id = 'saml:' . $spEntityId;
 
-			$associations[$id] = array(
-				'id' => $id,
-				'Handler' => 'sspmod_saml_IdP_SAML2',
-				'saml:entityID' => $spEntityId,
-				'saml:NameID' => $nameId,
-				'saml:SessionIndex' => $session->getSessionIndex(),
-			);
-		}
+	/**
+	 * Retrieve list of SP associations.
+	 *
+	 * @return array  List of SP associations.
+	 */
+	public function getAssociations() {
 
-		return $associations;
+		$session = SimpleSAML_Session::getInstance();
+		return $session->getAssociations($this->id);
 	}
 
 
@@ -178,10 +171,7 @@ class SimpleSAML_IdP {
 		assert('is_string($assocId)');
 
 		$session = SimpleSAML_Session::getInstance();
-
-		if (substr($assocId, 0, 5) === 'saml:') {
-			$session->set_sp_logout_completed(substr($assocId, 5));
-		}
+		$session->terminateAssociation($this->id, $assocId);
 	}
 
 
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index dc3bd1a2d3964fc2c3e3691e08a90b23f73aa924..2947d32ec133d78c1ebb48a5bdbf40e3edc993a2 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -14,10 +14,6 @@
  */
 class SimpleSAML_Session {
 
-	const STATE_ONLINE = 1;
-	const STATE_LOGOUTINPROGRESS = 2;
-	const STATE_LOGGEDOUT = 3;
-
 	/**
 	 * This is a timeout value for setData, which indicates that the data should be deleted
 	 * on logout.
@@ -89,6 +85,17 @@ class SimpleSAML_Session {
 	private $logoutState;
 
 
+	/**
+	 * The list of IdP-SP associations.
+	 *
+	 * This is an associative array with the IdP id as the key, and the list of
+	 * associations as the value.
+	 *
+	 * @var array
+	 */
+	private $associations = array();
+
+
 	/**
 	 * private constructor restricts instantiaton to getInstance()
 	 */
@@ -176,73 +183,8 @@ class SimpleSAML_Session {
 	public function getAuthority() {
 		return $this->authority;
 	}
-	
-	
-	
-	// *** SP list to be used with SAML 2.0 SLO ***
-	// *** *** *** *** *** *** *** *** *** *** ***
-	
-	public function add_sp_session($entityid) {
-		SimpleSAML_Logger::debug('Library - Session: Adding SP session: ' . $entityid);
-		$this->dirty = TRUE;
-		$this->sp_at_idpsessions[$entityid] = self::STATE_ONLINE;
-	}
-	
-	public function get_next_sp_logout() {
-		
-		if (!$this->sp_at_idpsessions) return null;
 
-		$this->dirty = TRUE;
-		
-		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
-			if ($sp == self::STATE_ONLINE) {
-				$this->sp_at_idpsessions[$entityid] = self::STATE_LOGOUTINPROGRESS;
-				return $entityid;
-			}
-		}
-		return null;
-	}
-	
-	public function get_sp_list($state = self::STATE_ONLINE) {
-		
-		$list = array();
-		if (!$this->sp_at_idpsessions) return $list;
-		
-		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
-			if ($sp == $state) {
-				$list[] = $entityid;
-			}
-		}
-		return $list;
-	}
-	
-	public function sp_logout_completed() {
 
-		if (!$this->sp_at_idpsessions) return TRUE;
-		
-		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
-			if ($sp != self::STATE_LOGGEDOUT) return FALSE;
-		}
-		return TRUE;
-	}
-	
-	
-	public function set_sp_logout_completed($entityid) {
-		SimpleSAML_Logger::debug('Library - Session: Setting SP state completed for : ' . $entityid);
-		$this->dirty = true;
-		$this->sp_at_idpsessions[$entityid] = self::STATE_LOGGEDOUT;
-	}
-	
-	public function dump_sp_sessions() {
-		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
-			SimpleSAML_Logger::debug('Dump sp sessions: ' . $entityid . ' status: ' . $sp);
-		}
-	}
-	// *** --- ***
-
-
-	
-	
 	/**
 	 * This method retrieves from session a cache of a specific Authentication Request
 	 * The complete request is not stored, instead the values that will be needed later
@@ -335,33 +277,11 @@ class SimpleSAML_Session {
 	}
 
 
-	/**
-	 * Set the NameID of the users session to the specified entity.
-	 *
-	 * @param string $entityType  The type of the entity (saml20-sp-remote, shib13-sp-remote, ...).
-	 * @param string $entityId  The entity id.
-	 * @param array $nameId  The name identifier.
-	 */
-	public function setSessionNameId($entityType, $entityId, $nameId) {
-		assert('is_string($entityType)');
-		assert('is_string($entityId)');
-		assert('is_array($nameId)');
-
-		if(!is_array($this->sessionNameId)) {
-			$this->sessionNameId = array();
-		}
-
-		if(!array_key_exists($entityType, $this->sessionNameId)) {
-			$this->sessionNameId[$entityType] = array();
-		}
-
-		$this->sessionNameId[$entityType][$entityId] = $nameId;
-	}
-
-
 	/**
 	 * Get the NameID of the users session to the specified entity.
 	 *
+	 * Deprecated, remove in version 1.7.
+	 *
 	 * @param string $entityType  The type of the entity (saml20-sp-remote, shib13-sp-remote, ...).
 	 * @param string $entityId  The entity id.
 	 * @return array  The name identifier, or NULL if no name identifier is associated with this session.
@@ -967,6 +887,150 @@ class SimpleSAML_Session {
 		return $sh->hasSessionCookie();
 	}
 
+
+	/**
+	 * Upgrade the association list to the new format.
+	 *
+	 * Should be removed in version 1.7.
+	 *
+	 * @param string $idp  The IdP we should add the associations to.
+	 */
+	private function upgradeAssociations($idp) {
+		assert('is_string($idp)');
+
+		$sp_at_idpsessions = $this->sp_at_idpsessions;
+		$this->sp_at_idpsessions = NULL;
+		$this->dirty = TRUE;
+
+		$globalConfig = SimpleSAML_Configuration::getInstance();
+		$sessionLifetime = time() + $globalConfig->getInteger('session.duration', 8*60*60);
+
+		foreach ($sp_at_idpsessions as $spEntityId => $state) {
+
+			if ($state !== 1) { /* 1 == STATE_ONLINE */
+				continue;
+			}
+
+			$nameId = $this->getSessionNameId('saml20-sp-remote', $spEntityId);
+			if($nameId === NULL) {
+				$nameId = $this->getNameID();
+			}
+
+			$id = 'saml:' . $spEntityId;
+
+			$this->addAssociation($idp, array(
+				'id' => $id,
+				'Handler' => 'sspmod_saml_IdP_SAML2',
+				'Expires' => $sessionLifetime,
+				'saml:entityID' => $spEntityId,
+				'saml:NameID' => $nameId,
+				'saml:SessionIndex' => $this->getSessionIndex(),
+			));
+		}
+	}
+
+
+	/**
+	 * Add an SP association for an IdP.
+	 *
+	 * This function is only for use by the SimpleSAML_IdP class.
+	 *
+	 * @param string $idp  The IdP id.
+	 * @param array $association  The association we should add.
+	 */
+	public function addAssociation($idp, array $association) {
+		assert('is_string($idp)');
+		assert('isset($association["id"])');
+		assert('isset($association["Handler"])');
+
+		if (substr($idp, 0, 6) === 'saml2:' && !empty($this->sp_at_idpsessions)) {
+			/* Remove in 1.7. */
+			$this->upgradeAssociations($idp);
+		}
+
+		if (!isset($this->associations)) {
+			$this->associations = array();
+		}
+
+		if (!isset($this->associations[$idp])) {
+			$this->associations[$idp] = array();
+		}
+
+		$this->associations[$idp][$association['id']] = $association;
+
+		$this->dirty = TRUE;
+	}
+
+
+	/**
+	 * Retrieve the associations for an IdP.
+	 *
+	 * This function is only for use by the SimpleSAML_IdP class.
+	 *
+	 * @param string $idp  The IdP id.
+	 * @return array  The IdP associations.
+	 */
+	public function getAssociations($idp) {
+		assert('is_string($idp)');
+
+		if (substr($idp, 0, 6) === 'saml2:' && !empty($this->sp_at_idpsessions)) {
+			/* Remove in 1.7. */
+			$this->upgradeAssociations($idp);
+		}
+
+		if (!isset($this->associations)) {
+			$this->associations = array();
+		}
+
+		if (!isset($this->associations[$idp])) {
+			return array();
+		}
+
+		foreach ($this->associations[$idp] as $id => $assoc) {
+			if (!isset($assoc['Expires'])) {
+				continue;
+			}
+			if ($assoc['Expires'] >= time()) {
+				continue;
+			}
+
+			unset($this->associations[$idp][$id]);
+		}
+
+		return $this->associations[$idp];
+	}
+
+
+	/**
+	 * Remove an SP association for an IdP.
+	 *
+	 * This function is only for use by the SimpleSAML_IdP class.
+	 *
+	 * @param string $idp  The IdP id.
+	 * @param string $associationId  The id of the association.
+	 */
+	public function terminateAssociation($idp, $associationId) {
+		assert('is_string($idp)');
+		assert('is_string($associationId)');
+
+		if (substr($idp, 0, 6) === 'saml2:' && !empty($this->sp_at_idpsessions)) {
+			/* Remove in 1.7. */
+			$this->upgradeAssociations($idp);
+		}
+
+		if (!isset($this->associations)) {
+			return;
+		}
+
+		if (!isset($this->associations[$idp])) {
+			return;
+		}
+
+		unset($this->associations[$idp][$associationId]);
+
+		$this->dirty = TRUE;
+	}
+
 }
 
 ?>
\ No newline at end of file
diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php
index 822bdf3891f9048a1d9a901e92ca3d6cedf076c1..e97cc9e731abf5000c0fe7a37c14e2cb992a910e 100644
--- a/modules/saml/lib/IdP/SAML2.php
+++ b/modules/saml/lib/IdP/SAML2.php
@@ -49,7 +49,15 @@ class sspmod_saml_IdP_SAML2 {
 		$assertion = sspmod_saml2_Message::buildAssertion($idpMetadata, $spMetadata, $attributes, $consumerURL);
 		$assertion->setInResponseTo($requestId);
 
-		$nameId = $assertion->getNameId();
+		/* Create the session association (for logout). */
+		$association = array(
+			'id' => 'saml:' . $spEntityId,
+			'Handler' => 'sspmod_saml_IdP_SAML2',
+			'Expires' => $assertion->getSessionNotOnOrAfter(),
+			'saml:entityID' => $spEntityId,
+			'saml:NameID' => $assertion->getNameId(),
+			'saml:SessionIndex' => $assertion->getSessionIndex(),
+		);
 
 		/* Maybe encrypt the assertion. */
 		$assertion = sspmod_saml2_Message::encryptAssertion($idpMetadata, $spMetadata, $assertion);
@@ -60,10 +68,8 @@ class sspmod_saml_IdP_SAML2 {
 		$ar->setRelayState($relayState);
 		$ar->setAssertions(array($assertion));
 
-		/* Add the session association (for logout). */
-		$session = SimpleSAML_Session::getInstance();
-		$session->add_sp_session($spEntityId);
-		$session->setSessionNameId('saml20-sp-remote', $spEntityId, $nameId);
+		/* Register the session association with the IdP. */
+		$idp->addAssociation($association);
 
 		/* Send the response. */
 		$binding = SAML2_Binding::getBinding($protocolBinding);