From 5a928c9198261d75c89c66c7a26bf183b2affed5 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sat, 26 May 2018 07:28:36 +0200 Subject: [PATCH] Can use security answers to create password reset token --- RestControllers/accountController.php | 48 +++++++++++++++++++++++++ classes/components/AccountComponent.php | 19 ++++++++++ db_struct.sql | 2 ++ 3 files changed, 69 insertions(+) diff --git a/RestControllers/accountController.php b/RestControllers/accountController.php index b62bf45..dde7557 100644 --- a/RestControllers/accountController.php +++ b/RestControllers/accountController.php @@ -127,6 +127,54 @@ class accountController { ); } + /** + * Check the security answers given by a user in order to reset its + * password + * + * @url POST /account/check_security_answers + */ + public function checkSecurityAnswers(){ + + //Get account ID + $userID = $this->getUserIDFromPostEmail("email"); + + //Check if user has defined security questions + if(!components()->settings->has_security_questions($userID)) + Rest_fatal_error(401, "Specified user has not set up security questions!"); + + //Get the security settings of the user + $settings = components()->settings->get_security($userID); + + //Check for errors + if(!$settings->isValid()) + Rest_fatal_error(500, "An error occurred while retrieving security settings of the user!"); + + //Get the list of security answers + $answersString = postString("answers", 3); + + //Get answers + $answers = explode("&", $answersString); + + //Check the number of given answers + if(count($answers) != 2) + Rest_fatal_error(401, "Please specify 2 security answers!"); + + //Check the security answers + if(strtolower(urldecode($answers[0])) != strtolower($settings->get_security_answer_1()) || + strtolower(urldecode($answers[1])) != strtolower($settings->get_security_answer_2())) + Rest_fatal_error(401, "Specified security answers are invalid!"); + + //If we get there, security anwsers are valid + $token = random_str(255); + if(!components()->account->set_new_password_reset_token($userID, $token)) + Rest_fatal_error(500, "Could not set a password reset token for the account!"); + + //Return result + return array( + "reset_token" => $token + ); + } + /** * Create an account * diff --git a/classes/components/AccountComponent.php b/classes/components/AccountComponent.php index 4e1e90e..c12e1b9 100644 --- a/classes/components/AccountComponent.php +++ b/classes/components/AccountComponent.php @@ -291,6 +291,25 @@ class AccountComponent { return CS::get()->db->updateDB(self::USER_TABLE, "ID = ?", $modif, array($userID)); } + /** + * Set new password reset token for an account + * + * @param int $userID Target user ID + * @param string $token The new token to apply + * @return bool TRUE for a success / FALSE else + */ + public function set_new_password_reset_token(int $userID, string $token) : bool { + + //Prepare database update + $modifs = array( + "pasword_reset_token" => $token, + "password_reset_token_time_create" => time() + ); + + //Apply update + return cs()->db->updateDB(self::USER_TABLE, "ID = ?", $modifs, array($userID)); + } + /** * Crypt user password * diff --git a/db_struct.sql b/db_struct.sql index fcdfc0f..510c6d7 100644 --- a/db_struct.sql +++ b/db_struct.sql @@ -484,5 +484,7 @@ CREATE TABLE `utilisateurs` ( `allow_multilogin` int(11) NOT NULL DEFAULT '0', `allow_piwik` int(11) NOT NULL DEFAULT '1', `public_note` varchar(255) DEFAULT NULL, + `pasword_reset_token` varchar(255) DEFAULT NULL, + `password_reset_token_time_create` int(11) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;