From 9de6bfbb442e78659527119fcb1e33d2c7cd86d6 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Fri, 13 Mar 2009 06:43:02 +0000
Subject: [PATCH] UserPassOrgBase: Allow organization to be part of the
 username

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1407 44740490-163a-0410-bde0-09ae8108e29a
---
 modules/core/lib/Auth/UserPassOrgBase.php | 67 ++++++++++++++++++++++-
 modules/core/www/loginuserpassorg.php     | 23 ++++----
 2 files changed, 79 insertions(+), 11 deletions(-)

diff --git a/modules/core/lib/Auth/UserPassOrgBase.php b/modules/core/lib/Auth/UserPassOrgBase.php
index ea45fba57..9f1d47bff 100644
--- a/modules/core/lib/Auth/UserPassOrgBase.php
+++ b/modules/core/lib/Auth/UserPassOrgBase.php
@@ -27,6 +27,16 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
 	const AUTHID = 'sspmod_core_Auth_UserPassOrgBase.AuthId';
 
 
+	/**
+	 * What way do we handle the organization as part of the username.
+	 * Three values:
+	 *  'none': Force the user to select the correct organization from the dropdown box.
+	 *  'allow': Allow the user to enter the organization as part of the username.
+	 *  'force': Remove the dropdown box.
+	 */
+	private $usernameOrgMethod;
+
+
 	/**
 	 * Constructor for this authentication source.
 	 *
@@ -42,6 +52,42 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
 
 		/* Call the parent constructor first, as required by the interface. */
 		parent::__construct($info, $config);
+
+		$this->usernameOrgMethod = 'none';
+	}
+
+
+	/**
+	 * Configure the way organizations as part of the username is handled.
+	 *
+	 * There are three possible values:
+	 * - 'none': Force the user to select the correct organization from the dropdown box.
+	 * - 'allow': Allow the user to enter the organization as part of the username.
+	 * - 'force': Remove the dropdown box.
+	 *
+	 * If unconfigured, the default is 'none'.
+	 *
+	 * @param string $usernameOrgMethod  The method which should be used.
+	 */
+	protected function setUsernameOrgMethod($usernameOrgMethod) {
+		assert('in_array($usernameOrgMethod, array("none", "allow", "force"), TRUE)');
+
+		$this->usernameOrgMethod = $usernameOrgMethod;
+	}
+
+
+	/**
+	 * Retrieve the way organizations as part of the username should be handled.
+	 *
+	 * There are three possible values:
+	 * - 'none': Force the user to select the correct organization from the dropdown box.
+	 * - 'allow': Allow the user to enter the organization as part of the username.
+	 * - 'force': Remove the dropdown box.
+	 *
+	 * @return string  The method which should be used.
+	 */
+	public function getUsernameOrgMethod() {
+		return $this->usernameOrgMethod;
 	}
 
 
@@ -127,6 +173,19 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
 			throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
 		}
 
+		$orgMethod = $source->getUsernameOrgMethod();
+		if ($orgMethod !== 'none') {
+			$tmp = explode('@', $username, 2);
+			if (count($tmp) === 2) {
+				$username = $tmp[0];
+				$organization = $tmp[1];
+			} else {
+				if ($orgMethod === 'force') {
+					/* The organization should be a part of the username, but isn't. */
+					return 'WRONGUSERPASS';
+				}
+			}
+		}
 
 		try {
 			/* Attempt to log in. */
@@ -157,7 +216,8 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
 	 * This function is used by the login form to get the available organizations.
 	 *
 	 * @param string $authStateId  The identifier of the authentication state.
-	 * @return array  Array of organizations.
+	 * @return array|NULL  Array of organizations. NULL if the user must enter the
+	 *         organization as part of the username.
 	 */
 	public static function listOrganizations($authStateId) {
 		assert('is_string($authStateId)');
@@ -172,6 +232,11 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
 			throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
 		}
 
+		$orgMethod = $source->getUsernameOrgMethod();
+		if ($orgMethod === 'force') {
+			return NULL;
+		}
+
 		return $source->getOrganizations();
 	}
 }
diff --git a/modules/core/www/loginuserpassorg.php b/modules/core/www/loginuserpassorg.php
index 27cb90206..3a3e0e190 100644
--- a/modules/core/www/loginuserpassorg.php
+++ b/modules/core/www/loginuserpassorg.php
@@ -14,6 +14,7 @@ if (!array_key_exists('AuthState', $_REQUEST)) {
 	throw new SimpleSAML_Error_BadRequest('Missing AuthState parameter.');
 }
 $authStateId = $_REQUEST['AuthState'];
+$organizations = sspmod_core_Auth_UserPassOrgBase::listOrganizations($authStateId);
 
 if (array_key_exists('username', $_REQUEST)) {
 	$username = $_REQUEST['username'];
@@ -30,25 +31,27 @@ if (array_key_exists('password', $_REQUEST)) {
 if (array_key_exists('organization', $_REQUEST)) {
 	$organization = $_REQUEST['organization'];
 } else {
-	$organization = NULL;
+	$organization = '';
 }
 
-if (!empty($organization) && (!empty($username) || !empty($password))) {
-	/* Organization and either username or password set - attempt to log in. */
-	$errorCode = sspmod_core_Auth_UserPassOrgBase::handleLogin($authStateId, $username, $password, $organization);
-} else {
-	$errorCode = NULL;
+$errorCode = NULL;
+if ($organizations === NULL || !empty($organization)) {
+	if (!empty($username) && !empty($password)) {
+		$errorCode = sspmod_core_Auth_UserPassOrgBase::handleLogin($authStateId, $username, $password, $organization);
+	}
 }
 
-$organizations = sspmod_core_Auth_UserPassOrgBase::listOrganizations($authStateId);
-
 $globalConfig = SimpleSAML_Configuration::getInstance();
 $t = new SimpleSAML_XHTML_Template($globalConfig, 'core:loginuserpass.php');
 $t->data['stateparams'] = array('AuthState' => $authStateId);
-$t->data['selectedOrg'] = $organization;
-$t->data['organizations'] = $organizations;
 $t->data['username'] = $username;
 $t->data['errorcode'] = $errorCode;
+
+if ($organizations !== NULL) {
+	$t->data['selectedOrg'] = $organization;
+	$t->data['organizations'] = $organizations;
+}
+
 $t->show();
 exit();
 
-- 
GitLab