From bcce2625a8cb0b630d945c6849014049869e10ce Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 27 Nov 2018 12:01:36 +0100 Subject: Implemented AuthController for login * Moved /login functionality to AuthController * Refactored password handling logic to use the Authenticator --- src/Controllers/AuthController.php | 90 ++++++++++++++++++++++++++- src/Helpers/Authenticator.php | 93 +++++++++++++++++++++++++--- src/Helpers/AuthenticatorServiceProvider.php | 4 ++ src/Middleware/LegacyMiddleware.php | 5 -- 4 files changed, 174 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php index cdaee167..e5fc40e3 100644 --- a/src/Controllers/AuthController.php +++ b/src/Controllers/AuthController.php @@ -2,8 +2,12 @@ namespace Engelsystem\Controllers; +use Carbon\Carbon; +use Engelsystem\Helpers\Authenticator; +use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Http\UrlGeneratorInterface; +use Engelsystem\Models\User\User; use Symfony\Component\HttpFoundation\Session\SessionInterface; class AuthController extends BaseController @@ -17,20 +21,100 @@ class AuthController extends BaseController /** @var UrlGeneratorInterface */ protected $url; - public function __construct(Response $response, SessionInterface $session, UrlGeneratorInterface $url) - { + /** @var Authenticator */ + protected $auth; + + /** @var array */ + protected $permissions = [ + 'login' => 'login', + 'postLogin' => 'login', + ]; + + /** + * @param Response $response + * @param SessionInterface $session + * @param UrlGeneratorInterface $url + * @param Authenticator $auth + */ + public function __construct( + Response $response, + SessionInterface $session, + UrlGeneratorInterface $url, + Authenticator $auth + ) { $this->response = $response; $this->session = $session; $this->url = $url; + $this->auth = $auth; + } + + /** + * @return Response + */ + public function login() + { + return $this->response->withView('pages/login'); + } + + /** + * Posted login form + * + * @param Request $request + * @return Response + */ + public function postLogin(Request $request): Response + { + $return = $this->authenticateUser($request->get('login', ''), $request->get('password', '')); + if (!$return instanceof User) { + return $this->response->withView( + 'pages/login', + ['errors' => [$return], 'show_password_recovery' => true] + ); + } + + $user = $return; + + $this->session->invalidate(); + $this->session->set('user_id', $user->id); + $this->session->set('locale', $user->settings->language); + + $user->last_login_at = new Carbon(); + $user->save(['touch' => false]); + + return $this->response->redirectTo('news'); } /** * @return Response */ - public function logout() + public function logout(): Response { $this->session->invalidate(); return $this->response->redirectTo($this->url->to('/')); } + + /** + * Verify the user and password + * + * @param $login + * @param $password + * @return User|string + */ + protected function authenticateUser(string $login, string $password) + { + if (!$login) { + return 'auth.no-nickname'; + } + + if (!$password) { + return 'auth.no-password'; + } + + if (!$user = $this->auth->authenticate($login, $password)) { + return 'auth.not-found'; + } + + return $user; + } } diff --git a/src/Helpers/Authenticator.php b/src/Helpers/Authenticator.php index 61d07980..db33339b 100644 --- a/src/Helpers/Authenticator.php +++ b/src/Helpers/Authenticator.php @@ -25,6 +25,9 @@ class Authenticator /** @var string[] */ protected $permissions; + /** @var int */ + protected $passwordAlgorithm = PASSWORD_DEFAULT; + /** * @param ServerRequestInterface $request * @param Session $session @@ -48,7 +51,7 @@ class Authenticator return $this->user; } - $userId = $this->session->get('uid'); + $userId = $this->session->get('user_id'); if (!$userId) { return null; } @@ -104,17 +107,15 @@ class Authenticator $abilities = (array)$abilities; if (empty($this->permissions)) { - $userId = $this->user ? $this->user->id : $this->session->get('uid'); + $user = $this->user(); - if ($userId) { - if ($user = $this->user()) { - $this->permissions = $this->getPermissionsByUser($user); + if ($user) { + $this->permissions = $this->getPermissionsByUser($user); - $user->last_login_at = new Carbon(); - $user->save(); - } else { - $this->session->remove('uid'); - } + $user->last_login_at = new Carbon(); + $user->save(); + } elseif ($this->session->get('user_id')) { + $this->session->remove('user_id'); } if (empty($this->permissions)) { @@ -131,6 +132,78 @@ class Authenticator return true; } + /** + * @param string $login + * @param string $password + * @return User|null + */ + public function authenticate(string $login, string $password) + { + /** @var User $user */ + $user = $this->userRepository->whereName($login)->first(); + if (!$user) { + $user = $this->userRepository->whereEmail($login)->first(); + } + + if (!$user) { + return null; + } + + if (!$this->verifyPassword($user, $password)) { + return null; + } + + return $user; + } + + /** + * @param User $user + * @param string $password + * @return bool + */ + public function verifyPassword(User $user, string $password) + { + $algorithm = $this->passwordAlgorithm; + + if (!password_verify($password, $user->password)) { + return false; + } + + if (password_needs_rehash($user->password, $algorithm)) { + $this->setPassword($user, $password); + } + + return true; + } + + /** + * @param UserRepository $user + * @param string $password + */ + public function setPassword(User $user, string $password) + { + $algorithm = $this->passwordAlgorithm; + + $user->password = password_hash($password, $algorithm); + $user->save(); + } + + /** + * @return int + */ + public function getPasswordAlgorithm() + { + return $this->passwordAlgorithm; + } + + /** + * @param int $passwordAlgorithm + */ + public function setPasswordAlgorithm(int $passwordAlgorithm) + { + $this->passwordAlgorithm = $passwordAlgorithm; + } + /** * @param User $user * @return array diff --git a/src/Helpers/AuthenticatorServiceProvider.php b/src/Helpers/AuthenticatorServiceProvider.php index 715a592f..f06e635d 100644 --- a/src/Helpers/AuthenticatorServiceProvider.php +++ b/src/Helpers/AuthenticatorServiceProvider.php @@ -2,14 +2,18 @@ namespace Engelsystem\Helpers; +use Engelsystem\Config\Config; use Engelsystem\Container\ServiceProvider; class AuthenticatorServiceProvider extends ServiceProvider { public function register() { + /** @var Config $config */ + $config = $this->app->get('config'); /** @var Authenticator $authenticator */ $authenticator = $this->app->make(Authenticator::class); + $authenticator->setPasswordAlgorithm($config->get('password_algorithm')); $this->app->instance(Authenticator::class, $authenticator); $this->app->instance('authenticator', $authenticator); diff --git a/src/Middleware/LegacyMiddleware.php b/src/Middleware/LegacyMiddleware.php index af2c6a70..7adcc88d 100644 --- a/src/Middleware/LegacyMiddleware.php +++ b/src/Middleware/LegacyMiddleware.php @@ -19,7 +19,6 @@ class LegacyMiddleware implements MiddlewareInterface 'angeltypes', 'atom', 'ical', - 'login', 'public_dashboard', 'rooms', 'shift_entries', @@ -175,10 +174,6 @@ class LegacyMiddleware implements MiddlewareInterface $title = settings_title(); $content = user_settings(); return [$title, $content]; - case 'login': - $title = login_title(); - $content = guest_login(); - return [$title, $content]; case 'register': $title = register_title(); $content = guest_register(); -- cgit v1.2.3-70-g09d2