diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/core/lib/Auth/UserPassBase.php | 136 | ||||
-rw-r--r-- | modules/core/templates/default/loginuserpass.php | 61 | ||||
-rw-r--r-- | modules/core/www/loginuserpass.php | 46 | ||||
-rw-r--r-- | modules/exampleauth/default-disable | 3 | ||||
-rw-r--r-- | modules/exampleauth/lib/Auth/Source/Static.php | 60 | ||||
-rw-r--r-- | modules/exampleauth/lib/Auth/Source/UserPass.php | 93 |
6 files changed, 399 insertions, 0 deletions
diff --git a/modules/core/lib/Auth/UserPassBase.php b/modules/core/lib/Auth/UserPassBase.php new file mode 100644 index 0000000..01a1b8f --- /dev/null +++ b/modules/core/lib/Auth/UserPassBase.php @@ -0,0 +1,136 @@ +<?php + +/** + * Helper class for username/password authentication. + * + * This helper class allows for implementations of username/password authentication by + * implementing a single function: login($username, $password) + * + * @author Olav Morken, UNINETT AS. + * @package simpleSAMLphp + * @version $Id$ + */ +abstract class sspmod_core_Auth_UserPassBase extends SimpleSAML_Auth_Source { + + + /** + * The string used to identify our states. + */ + const STAGEID = 'sspmod_core_Auth_UserPassBase.state'; + + + /** + * The key of the AuthId field in the state. + */ + const AUTHID = 'sspmod_core_Auth_UserPassBase.AuthId'; + + + /** + * Constructor for this authentication source. + * + * All subclasses who implement their own constructor must call this constructor before + * using $config for anything. + * + * @param array $info Information about this authentication source. + * @param array &$config Configuration for this authentication source. + */ + public function __construct($info, &$config) { + assert('is_array($info)'); + assert('is_array($config)'); + + /* Call the parent constructor first, as required by the interface. */ + parent::__construct($info, $config); + } + + + /** + * Initialize login. + * + * This function saves the information about the login, and redirects to a + * login page. + * + * @param array &$state Information about the current authentication. + */ + public function authenticate(&$state) { + assert('is_array($state)'); + + /* We are going to need the authId in order to retrieve this authentication source later. */ + $state[self::AUTHID] = $this->authId; + + $id = SimpleSAML_Auth_State::saveState($state, self::STAGEID); + + $url = SimpleSAML_Module::getModuleURL('core/loginuserpass.php'); + SimpleSAML_Utilities::redirect($url, array('AuthState' => $id)); + } + + + /** + * Attempt to log in using the given username and password. + * + * On a successful login, this function should return the users attributes. On failure, + * it should throw an exception/error. If the error was caused by the user entering the wrong + * username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown. + * + * Note that both the username and the password are UTF-8 encoded. + * + * @param string $username The username the user wrote. + * @param string $password The password the user wrote. + * @return array Associative array with the user's attributes. + */ + abstract protected function login($username, $password); + + + /** + * Handle login request. + * + * This function is used by the login form (core/www/loginuserpass.php) when the user + * enters a username and password. On success, it will not return. On wrong + * username/password failure, it will return the error code. Other failures will throw an + * exception. + * + * @param string $authStateId The identifier of the authentication state. + * @param string $username The username the user wrote. + * @param string $password The password the user wrote. + * @return string Error code in the case of an error. + */ + public static function handleLogin($authStateId, $username, $password) { + assert('is_string($authStateId)'); + assert('is_string($username)'); + assert('is_string($password)'); + + /* Retrieve the authentication state. */ + $state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID); + + /* Find authentication source. */ + assert('array_key_exists(self::AUTHID, $state)'); + $source = SimpleSAML_Auth_Source::getById($state[self::AUTHID]); + if ($source === NULL) { + throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]); + } + + + try { + /* Attempt to log in. */ + $attributes = $source->login($username, $password); + } catch (SimpleSAML_Error_Error $e) { + /* An error occured during login. Check if it is because of the wrong + * username/password - if it is, we pass that error up to the login form, + * if not, we let the generic error handler deal with it. + */ + if ($e->getErrorCode() === 'WRONGUSERPASS') { + return 'WRONGUSERPASS'; + } + + /* Some other error occured. Rethrow exception and let the generic error + * handler deal with it. + */ + throw $e; + } + + $state['Attributes'] = $attributes; + SimpleSAML_Auth_Source::completeAuth($state); + } + +} + +?>
\ No newline at end of file diff --git a/modules/core/templates/default/loginuserpass.php b/modules/core/templates/default/loginuserpass.php new file mode 100644 index 0000000..810abda --- /dev/null +++ b/modules/core/templates/default/loginuserpass.php @@ -0,0 +1,61 @@ +<?php +$this->data['icon'] = 'lock.png'; +$this->data['header'] = $this->t('{login:user_pass_header}'); + +if (strlen($this->data['username']) > 0) { + $this->data['autofocus'] = 'password'; +} else { + $this->data['autofocus'] = 'username'; +} +$this->includeAtTemplateBase('includes/header.php'); + +?> +<div id="content"> + +<?php +if ($this->data['errorcode'] !== NULL) { +?> + <div style="border-left: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8; background: #f5f5f5"> + <img src="/<?php echo $this->data['baseurlpath']; ?>resources/icons/bomb.png" style="float: left; margin: 15px " /> + <h2><?php echo $this->t('{login:error_header}'); ?></h2> + <p><b><?php echo $this->t('{errors:title_' . $this->data['errorcode'] . '}'); ?></b></p> + <p><?php echo $this->t('{errors:descr_' . $this->data['errorcode'] . '}'); ?></p> + </div> +<?php +} +?> + <h2 style="break: both"><?php echo $this->t('{login:user_pass_header}'); ?></h2> + + <p><?php echo $this->t('{login:user_pass_text}'); ?></p> + + <form action="?" method="post" name="f"> + + <table> + <tr> + <td rowspan="2"><img src="/<?php echo $this->data['baseurlpath']; ?>resources/icons/pencil.png" alt="" /></td> + <td style="padding: .3em;"><?php echo $this->t('{login:username}'); ?></td> + <td><input type="text" id="username" tabindex="1" name="username" value="<?php echo htmlspecialchars($this->data['username']); ?>" /></td> + <td style="padding: .4em;" rowspan="2"> + <input type="submit" tabindex="3" value="<?php echo $this->t('{login:login_button}'); ?>" /> + </td> + </tr> + <tr> + <td style="padding: .3em;"><?php echo $this->t('{login:password}'); ?></td> + <td><input id="password" type="password" tabindex="2" name="password" /></td> + </tr> + </table> + +<?php +foreach ($this->data['stateparams'] as $name => $value) { + echo('<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />'); +} +?> + + </form> + +<?php +echo('<h2>' . $this->t('{login:help_header}') . '</h2>'); +echo('<p>' . $this->t('{login:help_text}') . '</p>'); + +$this->includeAtTemplateBase('includes/footer.php'); +?>
\ No newline at end of file diff --git a/modules/core/www/loginuserpass.php b/modules/core/www/loginuserpass.php new file mode 100644 index 0000000..a7bfdb2 --- /dev/null +++ b/modules/core/www/loginuserpass.php @@ -0,0 +1,46 @@ +<?php + +/** + * This page shows a username/password login form, and passes information from it + * to the sspmod_core_Auth_UserPassBase class, which is a generic class for + * username/password authentication. + * + * @author Olav Morken, UNINETT AS. + * @package simpleSAMLphp + * @version $Id$ + */ + +if (!array_key_exists('AuthState', $_REQUEST)) { + throw new SimpleSAML_Error_BadRequest('Missing AuthState parameter.'); +} +$authStateId = $_REQUEST['AuthState']; + +if (array_key_exists('username', $_REQUEST)) { + $username = $_REQUEST['username']; +} else { + $username = ''; +} + +if (array_key_exists('password', $_REQUEST)) { + $password = $_REQUEST['password']; +} else { + $password = ''; +} + +if (!empty($username) || !empty($password)) { + /* Either username or password set - attempt to log in. */ + $errorCode = sspmod_core_Auth_UserPassBase::handleLogin($authStateId, $username, $password); +} else { + $errorCode = NULL; +} + +$globalConfig = SimpleSAML_Configuration::getInstance(); +$t = new SimpleSAML_XHTML_Template($globalConfig, 'core:loginuserpass.php'); +$t->data['stateparams'] = array('AuthState' => $authStateId); +$t->data['username'] = $username; +$t->data['errorcode'] = $errorCode; +$t->show(); +exit(); + + +?>
\ No newline at end of file diff --git a/modules/exampleauth/default-disable b/modules/exampleauth/default-disable new file mode 100644 index 0000000..fa0bd82 --- /dev/null +++ b/modules/exampleauth/default-disable @@ -0,0 +1,3 @@ +This file indicates that the default state of this module +is disabled. To enable, create a file named enable in the +same directory as this file. diff --git a/modules/exampleauth/lib/Auth/Source/Static.php b/modules/exampleauth/lib/Auth/Source/Static.php new file mode 100644 index 0000000..c2a07cc --- /dev/null +++ b/modules/exampleauth/lib/Auth/Source/Static.php @@ -0,0 +1,60 @@ +<?php + +/** + * Example authentication source. + * + * This class is an example authentication source which will always return a user with + * a static set of attributes. + * + * @author Olav Morken, UNINETT AS. + * @package simpleSAMLphp + * @version $Id$ + */ +class sspmod_exampleauth_Auth_Source_Static extends SimpleSAML_Auth_Source { + + + /** + * The attributes we return. + */ + private $attributes; + + + /** + * Constructor for this authentication source. + * + * @param array $info Information about this authentication source. + * @param array $config Configuration. + */ + public function __construct($info, $config) { + assert('is_array($info)'); + assert('is_array($config)'); + + /* Call the parent constructor first, as required by the interface. */ + parent::__construct($info, $config); + + + /* Parse attributes. */ + try { + $this->attributes = SimpleSAML_Utilities::parseAttributes($attributes); + } catch(Exception $e) { + throw new Exception('Invalid attributes for authentication source ' . + $this->authId . ': ' . $e->getMessage()); + } + + } + + + /** + * Log in using static attributes. + * + * @param array &$state Information about the current authentication. + */ + public function authenticate(&$state) { + assert('is_array($state)'); + + $state['Attributes'] = $this->attributes; + } + +} + +?>
\ No newline at end of file diff --git a/modules/exampleauth/lib/Auth/Source/UserPass.php b/modules/exampleauth/lib/Auth/Source/UserPass.php new file mode 100644 index 0000000..98440f5 --- /dev/null +++ b/modules/exampleauth/lib/Auth/Source/UserPass.php @@ -0,0 +1,93 @@ +<?php + +/** + * Example authentication source - username & password. + * + * This class is an example authentication source which stores all username/passwords in an array, + * and authenticates users against this array. + * + * @author Olav Morken, UNINETT AS. + * @package simpleSAMLphp + * @version $Id$ + */ +class sspmod_exampleauth_Auth_Source_UserPass extends sspmod_core_Auth_UserPassBase { + + + /** + * Our users, stored in an associative array. The key of the array is "<username>:<password>", + * while the value of each element is a new array with the attributes for each user. + */ + private $users; + + + /** + * Constructor for this authentication source. + * + * @param array $info Information about this authentication source. + * @param array $config Configuration. + */ + public function __construct($info, $config) { + assert('is_array($info)'); + assert('is_array($config)'); + + /* Call the parent constructor first, as required by the interface. */ + parent::__construct($info, $config); + + $this->users = array(); + + /* Validate and parse our configuration. */ + foreach ($config as $userpass => $attributes) { + if (!is_string($userpass)) { + throw new Exception('Invalid <username>:<password> for authentication source ' . + $this->authId . ': ' . $userpass); + } + + $userpass = explode(':', $userpass, 2); + if (count($userpass) !== 2) { + throw new Exception('Invalid <username>:<password> for authentication source ' . + $this->authId . ': ' . $userpass[0]); + } + $username = $userpass[0]; + $password = $userpass[1]; + + try { + $attributes = SimpleSAML_Utilities::parseAttributes($attributes); + } catch(Exception $e) { + throw new Exception('Invalid attributes for user ' . $username . + ' in authentication source ' . $this->authId . ': ' . + $e->getMessage()); + } + + $this->users[$username . ':' . $password] = $attributes; + } + } + + + /** + * Attempt to log in using the given username and password. + * + * On a successful login, this function should return the users attributes. On failure, + * it should throw an exception. If the error was caused by the user entering the wrong + * username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown. + * + * Note that both the username and the password are UTF-8 encoded. + * + * @param string $username The username the user wrote. + * @param string $password The password the user wrote. + * @return array Associative array with the users attributes. + */ + protected function login($username, $password) { + assert('is_string($username)'); + assert('is_string($password)'); + + $userpass = $username . ':' . $password; + if (!array_key_exists($userpass, $this->users)) { + throw new SimpleSAML_Error_Error('WRONGUSERPASS'); + } + + return $this->users[$userpass]; + } + +} + +?>
\ No newline at end of file |