Revision: 2145
Author: olavmrk
Date: Wed Jan 27 23:41:07 2010
Log: Session: New SP association infrastructure.
Fixes issue 180.
http://code.google.com/p/simplesamlphp/source/detail?r=2145
Modified:
/trunk/lib/SimpleSAML/IdP.php
/trunk/lib/SimpleSAML/Session.php
/trunk/modules/saml/lib/IdP/SAML2.php
=======================================
--- /trunk/lib/SimpleSAML/IdP.php Wed Jan 27 01:26:23 2010
+++ /trunk/lib/SimpleSAML/IdP.php Wed Jan 27 23:41:07 2010
@@ -137,35 +137,28 @@
/**
- * 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();
-
- $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(),
- );
- }
-
- return $associations;
+ $session->addAssociation($this->id, $association);
+ }
+
+
+ /**
+ * Retrieve list of SP associations.
+ *
+ * @return array List of SP associations.
+ */
+ public function getAssociations() {
+
+ $session = SimpleSAML_Session::getInstance();
+ return $session->getAssociations($this->id);
}
@@ -178,10 +171,7 @@
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);
}
=======================================
--- /trunk/lib/SimpleSAML/Session.php Wed Jan 27 01:26:48 2010
+++ /trunk/lib/SimpleSAML/Session.php Wed Jan 27 23:41:07 2010
@@ -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 @@
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 @@
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
@@ -333,35 +275,13 @@
return $this->nameid;
}
-
-
- /**
- * 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.
@@ -966,6 +886,150 @@
$sh = SimpleSAML_SessionHandler::getSessionHandler();
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;
+ }
}
=======================================
--- /trunk/modules/saml/lib/IdP/SAML2.php Wed Jan 27 01:26:39 2010
+++ /trunk/modules/saml/lib/IdP/SAML2.php Wed Jan 27 23:41:07 2010
@@ -49,7 +49,15 @@
$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 @@
$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);
--
You received this message because you are subscribed to the Google Groups
"simpleSAMLphp commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/simplesamlphp-commits?hl=en.