From c350ee34df0b2af6bc56cfc5efa0981f4fe81a93 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Sun, 7 Apr 2019 12:04:06 +0200 Subject: [PATCH] introduce AuthService --- ipf/admin/controllers/user.php | 5 ++-- ipf/admin/forms/login.php | 12 +++++--- ipf/auth/admin.php | 17 ++++++++---- ipf/auth/app.php | 7 ++++- ipf/auth/auth_service.php | 40 +++++++++++++++++++++++++++ ipf/auth/commands/createsuperuser.php | 9 ++++-- ipf/auth/models.php | 13 --------- ipf/crypto.php | 15 ---------- t/CryptoTest.php | 9 ------ 9 files changed, 76 insertions(+), 51 deletions(-) create mode 100644 ipf/auth/auth_service.php delete mode 100644 t/CryptoTest.php diff --git a/ipf/admin/controllers/user.php b/ipf/admin/controllers/user.php index c46efc3..81eff8d 100644 --- a/ipf/admin/controllers/user.php +++ b/ipf/admin/controllers/user.php @@ -21,15 +21,16 @@ class IPF_Admin_User_Controller extends IPF_Admin_Base_Controller $success_url = $this->container['router']->reverse(array('IPF_Admin_Dashboard_Controller', 'index')); $auth_app = $this->authApp(); + $auth_serice = $this->container['auth_service']; if ($this->request->method == 'POST') { - $form = new IPF_Admin_Forms_Login($this->request->POST, array('auth_app' => $auth_app)); + $form = new IPF_Admin_Forms_Login($this->request->POST, array('auth_app' => $auth_app, 'auth_service' => $auth_serice)); if ($form->isValid()) { $auth_app->login($this->request, $form->user); return new IPF_HTTP_Response_Redirect($success_url); } } else { - $form = new IPF_Admin_Forms_Login(array('next'=>$success_url), array('auth_app' => $auth_app)); + $form = new IPF_Admin_Forms_Login(array('next'=>$success_url), array('auth_app' => $auth_app, 'auth_service' => $auth_serice)); } $context = array( diff --git a/ipf/admin/forms/login.php b/ipf/admin/forms/login.php index 55289f3..3977318 100644 --- a/ipf/admin/forms/login.php +++ b/ipf/admin/forms/login.php @@ -7,10 +7,13 @@ class IPF_Admin_Forms_Login extends IPF_Form /** @var IPF_Auth_App */ private $auth_app; + /** @var \IPF\Auth\AuthService */ + private $auth_service; protected function initFields($extra=array()) { $this->auth_app = $extra['auth_app']; + $this->auth_service = $extra['auth_service']; $this->fields['username'] = new IPF_Form_Field_Varchar(array('required'=>true)); $this->fields['password'] = new IPF_Form_Field_Varchar(array('required'=>true,'widget'=>'IPF_Form_Widget_PasswordInput')); @@ -22,11 +25,12 @@ class IPF_Admin_Forms_Login extends IPF_Form $data = parent::clean(); $user = $this->auth_app->findUserByUsername($data['username']); - if (!$user || !$user->checkPassword($data['password'])) + if ($this->auth_service->checkPassword($user, $data['password'])) { + $this->user = $user; + return $data; + } else { throw new IPF_Exception_Form(__('The login or the password is not valid. The login and the password are case sensitive.')); - - $this->user = $user; - return $data; + } } public function render() diff --git a/ipf/auth/admin.php b/ipf/auth/admin.php index 76db597..c068cba 100644 --- a/ipf/auth/admin.php +++ b/ipf/auth/admin.php @@ -3,6 +3,7 @@ namespace IPF\Auth\Admin; use Doctrine\DBAL\Connection; +use IPF\Auth\AuthService; use IPF\Auth\Permission as Permission; use IPF\Auth\Role as Role; use IPF_Admin_App; @@ -116,11 +117,14 @@ abstract class Component extends \IPF_Admin_Component { /** @var Container */ protected $container; + /** @var AuthService */ + protected $auth_service; - function __construct(Container $container, IPF_Auth_App $auth_app) + function __construct(Container $container, IPF_Auth_App $auth_app, AuthService $auth_service) { $this->auth_app = $auth_app; $this->container = $container; + $this->auth_service = $auth_service; } /** @@ -262,8 +266,9 @@ class AdminUser extends Component $user = $this->authApp()->createUser(); $form->toObject($user); - if ($form->cleaned_data['password1']) - $user->setPassword($form->cleaned_data['password1']); + if ($form->cleaned_data['password1']) { + $this->auth_service->setPassword($user, $form->cleaned_data['password1']); + } $user->save($connection); if ($this->authApp()->arePermissionsEnabled()) { @@ -415,12 +420,14 @@ class AuthAdminSection implements \IPF_Admin_ISection { /** @var IPF_Auth_App $app */ + $auth_service = $container['auth_service']; + $components = array( - new AdminUser($container, $app), + new AdminUser($container, $app, $auth_service), ); if ($app->arePermissionsEnabled()) { - $components[] = new AdminRole($container, $app); + $components[] = new AdminRole($container, $app, $auth_service); } return $components; diff --git a/ipf/auth/app.php b/ipf/auth/app.php index a87b508..df14637 100644 --- a/ipf/auth/app.php +++ b/ipf/auth/app.php @@ -1,6 +1,7 @@ container = $container; $this->userModel = $container['settings']->get('auth_user_model', User::class); } @@ -83,7 +88,7 @@ class IPF_Auth_App extends IPF_Application public function commands() { return array( - new \IPF\Auth\Commands\CreateSuperUser($this), + new \IPF\Auth\Commands\CreateSuperUser($this, $this->container['auth_service']), ); } diff --git a/ipf/auth/auth_service.php b/ipf/auth/auth_service.php new file mode 100644 index 0000000..7633ed4 --- /dev/null +++ b/ipf/auth/auth_service.php @@ -0,0 +1,40 @@ +password = 'sha1:' . $salt . ':' . sha1($salt . $raw_password); + } else { + $user->password = ''; + } + } + + function checkPassword($user, $raw_password) + { + if ($raw_password && + $user && + $user->is_active && + $user->password && + strpos($user->password, ':') !== false + ) { + list($algo, $salt, $hash) = explode(':', $user->password); + return $hash === $algo($salt . $raw_password); + } else { + return false; + } + } +} diff --git a/ipf/auth/commands/createsuperuser.php b/ipf/auth/commands/createsuperuser.php index 43a179d..2722a71 100644 --- a/ipf/auth/commands/createsuperuser.php +++ b/ipf/auth/commands/createsuperuser.php @@ -2,6 +2,8 @@ namespace IPF\Auth\Commands; +use IPF\Auth\AuthService; + class CreateSuperUser { public $command = 'createsuperuser'; @@ -9,10 +11,13 @@ class CreateSuperUser /** @var \IPF_Auth_App */ private $auth_app; + /** @var AuthService */ + private $auth_service; - public function __construct(\IPF_Auth_App $auth_app) + public function __construct(\IPF_Auth_App $auth_app, AuthService $auth_service) { $this->auth_app = $auth_app; + $this->auth_service = $auth_service; } public function run($args=null) @@ -29,7 +34,7 @@ class CreateSuperUser $su->is_staff = true; $su->is_active = true; $su->is_superuser = true; - $su->setPassword($password); + $this->auth_service->setPassword($su, $password); $su->save(); print "Done\n"; } diff --git a/ipf/auth/models.php b/ipf/auth/models.php index 4af5767..1da877e 100644 --- a/ipf/auth/models.php +++ b/ipf/auth/models.php @@ -73,19 +73,6 @@ class User extends DBObject return $s; } - function setPassword($raw_password) - { - if ($raw_password) - $this->password = \IPF_Crypto::hashPassword($raw_password); - else - $this->password = ''; - } - - function checkPassword($raw_password) - { - return $this->is_active && \IPF_Crypto::checkPassword($raw_password, $this->password); - } - function isAnonymous() { return false; diff --git a/ipf/crypto.php b/ipf/crypto.php index 9722b49..f4624b7 100644 --- a/ipf/crypto.php +++ b/ipf/crypto.php @@ -22,20 +22,6 @@ class IPF_Crypto return hash_hmac('sha1', $string, self::get_key()); } - public static function hashPassword($rawPassword) - { - $salt = IPF_Utils::randomString(5); - return 'sha1:'.$salt.':'.sha1($salt . $rawPassword); - } - - public static function checkPassword($rawPassword, $hashedPassword) - { - if (!$rawPassword || !$hashedPassword || strpos($hashedPassword, ':') === false) - return false; - list($algo, $salt, $hash) = explode(':', $hashedPassword); - return $hash === $algo($salt . $rawPassword); - } - private static function get_key() { $secret = self::secretKey(); @@ -57,4 +43,3 @@ class IPF_Crypto throw new Exception('Security error: "secret_key" is not set in the configuration file.'); } } - diff --git a/t/CryptoTest.php b/t/CryptoTest.php deleted file mode 100644 index d865881..0000000 --- a/t/CryptoTest.php +++ /dev/null @@ -1,9 +0,0 @@ -assertFalse(IPF_Crypto::checkPassword('secret', 'badhash')); - } -} -- 2.49.0