From f2c2e6ea5e4f77dd3b53f83655ffd81adc971bec Mon Sep 17 00:00:00 2001
From: Andjelko Horvat <comel@vingd.com>
Date: Fri, 13 Sep 2013 11:04:39 +0000
Subject: [PATCH] Add remember me feature (patch 2 from issue #571).

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3276 44740490-163a-0410-bde0-09ae8108e29a
---
 config-templates/config.php     | 17 +++++++
 lib/SimpleSAML/Auth/Default.php |  4 +-
 lib/SimpleSAML/Session.php      | 85 ++++++++++++++++++++++++++++++++-
 3 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/config-templates/config.php b/config-templates/config.php
index 4a286d3fd..ca7f2e463 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -290,6 +290,23 @@ $config = array (
 	 */
 	'session.authtoken.cookiename' => 'SimpleSAMLAuthToken',
 
+	/*
+	 * Options for remember me feature for IdP sessions. Remember me feature
+	 * has to be also implemented in authentication source used.
+	 *
+	 * Option 'session.cookie.lifetime' should be set to zero (0), i.e. cookie
+	 * expires on browser session if remember me is not checked.
+	 *
+	 * Session duration ('session.duration' option) should be set according to
+	 * 'session.rememberme.lifetime' option.
+	 *
+	 * It's advised to use remember me feature with session checking function
+	 * defined with 'session.check_function' option.
+	 */
+	'session.rememberme.enable' => FALSE,
+	'session.rememberme.checked' => FALSE,
+	'session.rememberme.lifetime' => (14*86400),
+
 	/**
 	 * Custom function for session checking called on session init and loading.
 	 * See docs/simplesamlphp-advancedfeatures.txt for function code example.
diff --git a/lib/SimpleSAML/Auth/Default.php b/lib/SimpleSAML/Auth/Default.php
index de5873c8a..39cc174f3 100644
--- a/lib/SimpleSAML/Auth/Default.php
+++ b/lib/SimpleSAML/Auth/Default.php
@@ -91,7 +91,7 @@ class SimpleSAML_Auth_Default {
 		}
 
 		/* Add those that should always be included. */
-		foreach (array('Attributes', 'Expire', 'LogoutState', 'AuthnInstant') as $a) {
+		foreach (array('Attributes', 'Expire', 'LogoutState', 'AuthnInstant', 'RememberMe') as $a) {
 			if (isset($state[$a])) {
 				$persistentAuthState[$a] = $state[$a];
 			}
@@ -255,5 +255,3 @@ class SimpleSAML_Auth_Default {
 	}
 
 }
-
-?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index b7151a98b..404b54819 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -80,7 +80,9 @@ class SimpleSAML_Session {
 	// Session duration parameters
 	private $sessionstarted = null;
 	private $sessionduration = null;
-	
+
+	private $rememberMeExpire = null;
+
 	// Track whether the session object is modified or not.
 	private $dirty = false;
 		
@@ -500,6 +502,52 @@ class SimpleSAML_Session {
 	}
 
 
+	/**
+	 * Set remember me expire time.
+	 *
+	 * @param int $expire  Unix timestamp when remember me session cookies expire.
+	 */
+	public function setRememberMeExpire($expire = NULL) {
+		assert('is_int($expire) || is_null($expire)');
+
+		if ($expire === NULL) {
+			$globalConfig = SimpleSAML_Configuration::getInstance();
+			$expire = time() + $globalConfig->getInteger('session.rememberme.lifetime', 14*86400);
+		}
+		$this->rememberMeExpire = $expire;
+
+		$cookieParams = array('expire' => $this->rememberMeExpire);
+		$this->updateSessionCookies($cookieParams);
+	}
+
+
+	/**
+	 * Get remember me expire time.
+	 *
+	 * @return integer|NULL The remember me expire time.
+	 */
+	public function getRememberMeExpire() {
+		return $this->rememberMeExpire;
+	}
+
+
+	/**
+	 * Update session cookies.
+	 */
+	public function updateSessionCookies($params = NULL) {
+		$sessionHandler = SimpleSAML_SessionHandler::getSessionHandler();
+
+		if ($this->sessionId !== NULL) {
+			$sessionHandler->setCookie($sessionHandler->getSessionCookieName(), $this->sessionId, $params);
+		}
+
+		if ($this->authToken !== NULL) {
+			$globalConfig = SimpleSAML_Configuration::getInstance();
+			$sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'), $this->authToken, $params);
+		}
+	}
+
+
 	/**
 	 * Marks the user as logged in with the specified authority.
 	 *
@@ -526,6 +574,8 @@ class SimpleSAML_Session {
 			$data = array();
 		}
 
+		$data['Authority'] = $authority;
+
 		$globalConfig = SimpleSAML_Configuration::getInstance();
 		if (!isset($data['AuthnInstant'])) {
 			$data['AuthnInstant'] = time();
@@ -542,7 +592,12 @@ class SimpleSAML_Session {
 
 		$this->authToken = SimpleSAML_Utilities::generateID();
 		$sessionHandler = SimpleSAML_SessionHandler::getSessionHandler();
-		$sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'), $this->authToken);
+
+		if (!$this->transient && (!empty($data['RememberMe']) || $this->rememberMeExpire) && $globalConfig->getBoolean('session.rememberme.enable', FALSE)) {
+			$this->setRememberMeExpire();
+		} else {
+			$sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'), $this->authToken);
+		}
 	}
 
 
@@ -578,11 +633,37 @@ class SimpleSAML_Session {
 			$this->authority = NULL;
 		}
 
+		if ($this->authority === NULL && $this->rememberMeExpire) {
+			$this->rememberMeExpire = NULL;
+			$this->updateSessionCookies();
+		}
+
 		/* Delete data which expires on logout. */
 		$this->expireDataLogout();
 	}
 
 
+	/**
+	 * Set the lifetime for authentication source.
+	 *
+	 * @param string $authority  The authentication source we are setting expire time for.
+	 * @param int $expire  The number of seconds authentication source is valid.
+	 */
+	public function setAuthorityExpire($authority, $expire = NULL) {
+		assert('isset($this->authData[$authority])');
+		assert('is_int($expire) || is_null($expire)');
+
+		$this->dirty = true;
+
+		if ($expire === NULL) {
+			$globalConfig = SimpleSAML_Configuration::getInstance();
+			$expire = time() + $globalConfig->getInteger('session.duration', 8*60*60);
+		}
+
+		$this->authData[$authority]['Expire'] = $expire;
+	}
+
+
 	/**
 	 * Set the lifetime of our current authentication session.
 	 *
-- 
GitLab