diff --git a/README.md b/README.md index fc1b539..2f230b1 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ This app has no user interface. All configuration is done via Nextcloud's system //'db_password' => 'thePasswordForTheDatabaseUser', //'db_password_file' => '/path/to/file/ContainingThePasswordForTheDatabaseUser', 'queries' => array( - 'get_password_hash_for_user' => 'SELECT password_hash FROM users_fqda WHERE fqda = :username', + 'get_password_hash_for_user' => 'SELECT password_hash, fqda FROM users_fqda WHERE fqda = :username OR email = :username', 'user_exists' => 'SELECT EXISTS(SELECT 1 FROM users_fqda WHERE fqda = :username)', 'get_users' => 'SELECT fqda FROM users_fqda WHERE (fqda ILIKE :search) OR (display_name ILIKE :search)', //'set_password_hash_for_user' => 'UPDATE users SET password_hash = :new_password_hash WHERE local = split_part(:username, \'@\', 1) AND domain = split_part(:username, \'@\', 2)', @@ -130,7 +130,10 @@ that will be used to read/write data. * queries use named parameters. You have to use the exact names as shown in the examples. For example, to retrieve the hash for a user, the query named `get_password_hash_for_user` will be used. Write your custom SQL query and simply put `:username` where you are referring to the - username (aka uid) of the user trying to login. + username (aka uid) of the user trying to login. Optionally the query may return a second column + with the uid as nexcloud should use it. This allows you to accept multiple usernames (e.g. + username and email, case insensitive usernames, etc) for a single account. This uid will then + also be used in subsequent queries .If not present the username as entered will be used. * You don't need to supply all queries. For example, if you use the default user home simply leave the query `get_home` commented. This app will recognize this and [communicate](https://github.com/nextcloud/server/blob/316acc3cc313f4333fe29d136f9124f163b40dec/lib/public/UserInterface.php#L47) @@ -138,7 +141,8 @@ that will be used to read/write data. * `user_exists` and `get_users` are required, the rest is optional. * For user authentication (i.e. login) you need at least `get_password_hash_for_user`, `user_exists` and `get_users`. -* For all queries that read data, only the first column is interpreted. +* For all queries that read data except get_password_hash_for_user (see above), only the first + column is interpreted. * Two queries require a little bit of attention: 1. `user_exists` should return a boolean. See the example on how to do this properly. 2. `get_users` is a query that searches for usernames (e.g. *bob*) and display names (e.g. *Bob diff --git a/lib/UserBackend.php b/lib/UserBackend.php index 8bd833a..2240c52 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -23,6 +23,7 @@ use OC\User\Backend; use Psr\Log\LoggerInterface; +use \PDO; class UserBackend implements \OCP\IUserBackend, \OCP\UserInterface @@ -67,7 +68,7 @@ public function implementsActions($actions) * Nextcloud if Backend::CHECK_PASSWORD is set. * @param $providedUsername * @param $providedPassword - * @return bool whether the provided password was correct for provided user + * @return string|false The uid on success false on failure */ public function checkPassword($providedUsername, $providedPassword) { @@ -80,14 +81,19 @@ public function checkPassword($providedUsername, $providedPassword) $statement = $dbHandle->prepare($this->config->getQueryGetPasswordHashForUser()); $statement->execute(['username' => $providedUsername]); - $retrievedPasswordHash = $statement->fetchColumn(); - - if ($retrievedPasswordHash === false) { + $retrievedRow = $statement->fetch(PDO::FETCH_NUM); + if ($retrievedRow === false || count($retrievedRow) == 0) { return false; } + $retrievedPasswordHash = $retrievedRow[0]; + if (password_verify($providedPassword, $retrievedPasswordHash)) { - return $providedUsername; + if (count($retrievedRow) > 1) { + return $retrievedRow[1]; + } else { + return $providedUsername; + } } else { return false; }