diff --git a/README.md b/README.md index 110aae7..a8de1ac 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,19 @@ This fork adds support for SQL databases as the back-end. The module needs an `sqlauth:SQL` authentication source as the place to store user accounts. You can use an existing authsource, just make sure the credentials used allow for writing. People that want to sign up for an account need to fill in their e-mail address, and they get sent a URL with a token to confirm the address. -Upon verification the user can then needs choose a username, a password, and values for first and last name. +Upon verification the user can then needs choose a username (unless auto-generation is configured, see below), a password, and values for first and last name. These values are stored in the SQL back-end. To store the password securely it is hashed with a salt, which is saved in a separate database column. This approach allows the database to do the password verification. Enable this module the standard way (i.e. touching the file `enable` in the module directory, and copy the default configuration file to `config/`). MySQL back-end -============== - +-------------- The default configuration file `module_selfregister.php` contains all the necessary statements. -###Database set-up +### Database set-up Create the database, add a user, and assign permissions: @@ -44,8 +43,8 @@ Create the table that will hold you users: ) -###authsource set-up --------------------- +### authsource set-up + Create the accompanying authsource in `config/authsources.php`: 'selfregister-mysql' => array( @@ -66,9 +65,9 @@ Create the accompanying authsource in `config/authsources.php`: PostgreSQL back-end -=================== +------------------- -###Database set-up +### Database set-up As the postgres super user, create a new role, and a new database that is owner by the new user: @@ -82,7 +81,7 @@ In order to use the crypto that is needed to do the password verification, you n This in turn might depend on an extra package, for Debian/Ubuntu this is the `postgresql-contrib` package. -####authsource set-up +### authsource set-up Create the accompanying authsource in `config/authsources.php` (and remember to update the `auth` statement in `module_selfregister.php`_: @@ -101,7 +100,7 @@ Create the accompanying authsource in `config/authsources.php` (and remember to Attribute mapping -================= +----------------- Add the follwoing authproc filter to the IdP metadata (metadata/saml20-idp-hosted.php), so that the attributes will have the standard names: @@ -116,3 +115,22 @@ Add the follwoing authproc filter to the IdP metadata (metadata/saml20-idp-hoste 'firstname' => 'givenName', ), + +Log in with email address +------------------------- + +> N.B.: This feature is currently only implemented for the SQL storage backend, not for LDAP. + +Deployments that want to use the subject's email address as login name/userid can set the option `user.id.autocreate` to `true` in `config/module_selfregister.php`. This will cause the `userid` value to be filled automatically (more or less randomly), without the subject having to chose and remember Yet Another username during registration. +(Note that the string `Username` then might also need to be changed in the relevant dictionaries to state "Email address" instead, to avoid confusion about just what to enter during login.) + +To prevent the username field and description from showing up during registration also disable (uncomment or delete) the mapping of `username` within the `$attributes` array in your `config/module_selfregister.php`, such as below: + + 'attributes' => array( + //'username' => 'uid', // Removed, we use user.id.autocreate instead + 'firstname' => 'givenName', + 'lastname' => 'sn', + 'email' => 'mail', + 'userPassword' => 'password', + ), + diff --git a/config-templates/module_selfregister.php b/config-templates/module_selfregister.php index dcdecda..d6eef77 100644 --- a/config-templates/module_selfregister.php +++ b/config-templates/module_selfregister.php @@ -38,6 +38,11 @@ // This is usually the primary key // This relates to the attributs mapping (see below) 'user.id.param' => 'userid', + + // Whether to create unique userids programmatically instead of + // having the subject pick a userid during registration. + // Useful if you re-use the email addresses as login name. + 'user.id.autocreate' => false, ), // end SQL config @@ -46,7 +51,7 @@ 'attributes' => array( - 'username' => 'uid', + 'username' => 'uid', // comment out this line if you set user.id.autocreate to true 'firstname' => 'givenName', 'lastname' => 'sn', 'email' => 'mail', @@ -275,4 +280,4 @@ ), */ -); \ No newline at end of file +); diff --git a/lib/Storage/SqlMod.php b/lib/Storage/SqlMod.php index 23cdeb8..fa9d774 100644 --- a/lib/Storage/SqlMod.php +++ b/lib/Storage/SqlMod.php @@ -44,7 +44,8 @@ public function __construct($authSourceConfig, $writeConfig, $attributes, $hashA $this->salt = bin2hex(SimpleSAML_Utilities::generateRandomBytes(64)); $wc = SimpleSAML_Configuration::loadFromArray($writeConfig); $this->userIdAttr = $wc->getString('user.id.param'); - + $this->userIdAutoCreate = $wc->getBoolean('user.id.autocreate', false); + //$this->userIdAutoCreateLength = $wc->getInteger('user.id.autocreate.length', 9); } public function addUser($entry){ @@ -57,8 +58,11 @@ public function addUser($entry){ } else { - //$userid = $this->createUniqueUserId($entry['email']); - $userid = $entry['username']; + if ($this->userIdAutoCreate) { + $userid = $this->createUniqueUserId(); + } else { + $userid = $entry['username']; + } $sth = $this->dbh->prepare(" INSERT INTO users (userid, email, password, salt, firstname, lastname, created, updated) @@ -71,6 +75,31 @@ public function addUser($entry){ } } + public function createUniqueUserId() { + $userid = $this->createUserId(); + while ($this->isRegistered($this->userIdAttr, $userid)) { + $userid = $this->createUserId($string); + } + return $userid; + } + + private function createUserId() { + // Ideas cf. http://stackoverflow.com/questions/2799495/generate-unique-random-alphanumeric-characters-that-are-7-characters-long + + // Avoid chars that might be mistaken by a human (no [oO0il1]). + // Also is easily configurable wrt string length. + // Duplicates w/ deleted accounts are more likely over time, though. + // (All non-transient SAML identifiers require non-reassignment: subject-id, pairwise-id, persistent NameID, etc.) + //return substr( str_shuffle('abcdefghjkmnpqrstuvwxyz23456789'), 0, $this->userIdAutoCreateLength); // configurable length + + // Makes duplicates w/ deleted accounts less likely, but can't rule those out completely. + // Not easily configureable wrt string length. + //return base_convert(mt_rand(100, 999) . intval(microtime(true) * 10), 10, 36); // 9 chars + + // Time-based, so no duplicate ids even with deleted accounts. + return uniqid(); // 13 chars + } + private function hash_pass($plainPassword) { $salt = $this->salt; @@ -170,4 +199,4 @@ public function findAndGetUser($searchKeyName, $value) { } -?> \ No newline at end of file +?>