mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 17:45:39 +00:00
More authentication refactoring to also provide "plugable" credentials handling (references #921, needed for #305)
This commit is contained in:
parent
9f88dd3af3
commit
94214b867a
7
app.php
7
app.php
@ -11,9 +11,7 @@ require_once __DIR__ . '/vendor/autoload.php';
|
|||||||
|
|
||||||
// Load config files
|
// Load config files
|
||||||
require_once GROCY_DATAPATH . '/config.php';
|
require_once GROCY_DATAPATH . '/config.php';
|
||||||
require_once __DIR__ . '/config-dist.php';
|
require_once __DIR__ . '/config-dist.php'; // For not in own config defined values we use the default ones
|
||||||
|
|
||||||
// For not in own config defined values we use the default ones
|
|
||||||
|
|
||||||
// Definitions for dev/demo/prerelease mode
|
// Definitions for dev/demo/prerelease mode
|
||||||
if ((GROCY_MODE === 'dev' || GROCY_MODE === 'demo' || GROCY_MODE === 'prerelease') && !defined('GROCY_USER_ID'))
|
if ((GROCY_MODE === 'dev' || GROCY_MODE === 'demo' || GROCY_MODE === 'prerelease') && !defined('GROCY_USER_ID'))
|
||||||
@ -41,9 +39,6 @@ $container = $app->getContainer();
|
|||||||
$container->set('view', function (Container $container) {
|
$container->set('view', function (Container $container) {
|
||||||
return new Slim\Views\Blade(__DIR__ . '/views', GROCY_DATAPATH . '/viewcache');
|
return new Slim\Views\Blade(__DIR__ . '/views', GROCY_DATAPATH . '/viewcache');
|
||||||
});
|
});
|
||||||
$container->set('LoginControllerInstance', function (Container $container) {
|
|
||||||
return new LoginController($container, 'grocy_session');
|
|
||||||
});
|
|
||||||
$container->set('UrlManager', function (Container $container) {
|
$container->set('UrlManager', function (Container $container) {
|
||||||
return new UrlManager(GROCY_BASE_URL);
|
return new UrlManager(GROCY_BASE_URL);
|
||||||
});
|
});
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace Grocy\Controllers;
|
namespace Grocy\Controllers;
|
||||||
|
|
||||||
|
use Grocy\Services\SessionService;
|
||||||
|
|
||||||
class LoginController extends BaseController
|
class LoginController extends BaseController
|
||||||
{
|
{
|
||||||
protected $SessionCookieName;
|
public function __construct(\DI\Container $container)
|
||||||
|
|
||||||
public function GetSessionCookieName()
|
|
||||||
{
|
{
|
||||||
return $this->SessionCookieName;
|
parent::__construct($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LoginPage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
public function LoginPage(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||||
@ -18,50 +18,20 @@ class LoginController extends BaseController
|
|||||||
|
|
||||||
public function Logout(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
public function Logout(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||||
{
|
{
|
||||||
$this->getSessionService()->RemoveSession($_COOKIE[$this->SessionCookieName]);
|
$this->getSessionService()->RemoveSession($_COOKIE[SessionService::SESSION_COOKIE_NAME]);
|
||||||
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/'));
|
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ProcessLogin(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
public function ProcessLogin(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||||
{
|
{
|
||||||
$postParams = $this->GetParsedAndFilteredRequestBody($request);
|
$authMiddlewareClass = GROCY_AUTH_CLASS;
|
||||||
|
if ($authMiddlewareClass::ProcessLogin($this->GetParsedAndFilteredRequestBody($request)))
|
||||||
if (isset($postParams['username']) && isset($postParams['password']))
|
|
||||||
{
|
{
|
||||||
$user = $this->getDatabase()->users()->where('username', $postParams['username'])->fetch();
|
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/'));
|
||||||
$inputPassword = $postParams['password'];
|
|
||||||
$stayLoggedInPermanently = $postParams['stay_logged_in'] == 'on';
|
|
||||||
|
|
||||||
if ($user !== null && password_verify($inputPassword, $user->password))
|
|
||||||
{
|
|
||||||
$sessionKey = $this->getSessionService()->CreateSession($user->id, $stayLoggedInPermanently);
|
|
||||||
setcookie($this->SessionCookieName, $sessionKey, PHP_INT_SIZE == 4 ? PHP_INT_MAX : PHP_INT_MAX >> 32);
|
|
||||||
|
|
||||||
// Cookie expires never, but session validity is up to SessionService
|
|
||||||
|
|
||||||
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
|
|
||||||
{
|
|
||||||
$user->update([
|
|
||||||
'password' => password_hash($inputPassword, PASSWORD_DEFAULT)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/'));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/login?invalid=true'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/login?invalid=true'));
|
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/login?invalid=true'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(\DI\Container $container, string $sessionCookieName)
|
|
||||||
{
|
|
||||||
parent::__construct($container);
|
|
||||||
$this->SessionCookieName = $sessionCookieName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -72,4 +72,9 @@ class ApiKeyAuthMiddleware extends AuthMiddleware
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function ProcessLogin(array $postParams)
|
||||||
|
{
|
||||||
|
throw new \Exception('Not implemented');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,19 @@ abstract class AuthMiddleware extends BaseMiddleware
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function SetSessionCookie($sessionKey)
|
||||||
|
{
|
||||||
|
// Cookie never expires, session validity is up to SessionService
|
||||||
|
setcookie(SessionService::SESSION_COOKIE_NAME, $sessionKey, PHP_INT_SIZE == 4 ? PHP_INT_MAX : PHP_INT_MAX >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $postParams
|
||||||
|
* @return bool True/False if the provided credentials were valid
|
||||||
|
* @throws \Exception Throws an \Exception if an error happended during credentials processing or if this AuthMiddleware doesn't provide credentials processing (e. g. handles this externally)
|
||||||
|
*/
|
||||||
|
abstract public static function ProcessLogin(array $postParams);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return mixed|null the user row or null if the request is not authenticated
|
* @return mixed|null the user row or null if the request is not authenticated
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Grocy\Middleware;
|
namespace Grocy\Middleware;
|
||||||
|
|
||||||
|
use Grocy\Services\DatabaseService;
|
||||||
|
use Grocy\Services\SessionService;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
class DefaultAuthMiddleware extends AuthMiddleware
|
class DefaultAuthMiddleware extends AuthMiddleware
|
||||||
@ -22,4 +24,39 @@ class DefaultAuthMiddleware extends AuthMiddleware
|
|||||||
$user = $auth->authenticate($request);
|
$user = $auth->authenticate($request);
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function ProcessLogin(array $postParams)
|
||||||
|
{
|
||||||
|
if (isset($postParams['username']) && isset($postParams['password']))
|
||||||
|
{
|
||||||
|
$db = DatabaseService::getInstance()->GetDbConnection();
|
||||||
|
|
||||||
|
$user = $db->users()->where('username', $postParams['username'])->fetch();
|
||||||
|
$inputPassword = $postParams['password'];
|
||||||
|
$stayLoggedInPermanently = $postParams['stay_logged_in'] == 'on';
|
||||||
|
|
||||||
|
if ($user !== null && password_verify($inputPassword, $user->password))
|
||||||
|
{
|
||||||
|
$sessionKey = SessionService::getInstance()->CreateSession($user->id, $stayLoggedInPermanently);
|
||||||
|
parent::SetSessionCookie($sessionKey);
|
||||||
|
|
||||||
|
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
|
||||||
|
{
|
||||||
|
$user->update([
|
||||||
|
'password' => password_hash($inputPassword, PASSWORD_DEFAULT)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,9 @@ class ReverseProxyAuthMiddleware extends AuthMiddleware
|
|||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function ProcessLogin(array $postParams)
|
||||||
|
{
|
||||||
|
throw new \Exception('Not implemented');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,9 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
|||||||
|
|
||||||
class SessionAuthMiddleware extends AuthMiddleware
|
class SessionAuthMiddleware extends AuthMiddleware
|
||||||
{
|
{
|
||||||
protected $SessionCookieName;
|
|
||||||
|
|
||||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||||
{
|
{
|
||||||
parent::__construct($container, $responseFactory);
|
parent::__construct($container, $responseFactory);
|
||||||
$this->SessionCookieName = $this->AppContainer->get('LoginControllerInstance')->GetSessionCookieName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function authenticate(Request $request)
|
public function authenticate(Request $request)
|
||||||
@ -25,13 +22,18 @@ class SessionAuthMiddleware extends AuthMiddleware
|
|||||||
|
|
||||||
$sessionService = SessionService::getInstance();
|
$sessionService = SessionService::getInstance();
|
||||||
|
|
||||||
if (!isset($_COOKIE[$this->SessionCookieName]) || !$sessionService->IsValidSession($_COOKIE[$this->SessionCookieName]))
|
if (!isset($_COOKIE[SessionService::SESSION_COOKIE_NAME]) || !$sessionService->IsValidSession($_COOKIE[SessionService::SESSION_COOKIE_NAME]))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return $sessionService->GetUserBySessionKey($_COOKIE[$this->SessionCookieName]);
|
return $sessionService->GetUserBySessionKey($_COOKIE[SessionService::SESSION_COOKIE_NAME]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function ProcessLogin(array $postParams)
|
||||||
|
{
|
||||||
|
throw new \Exception('Not implemented');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ $app->group('', function (RouteCollectorProxy $group) {
|
|||||||
$group->get('/barcodescannertesting', '\Grocy\Controllers\SystemController:BarcodeScannerTesting');
|
$group->get('/barcodescannertesting', '\Grocy\Controllers\SystemController:BarcodeScannerTesting');
|
||||||
|
|
||||||
// Login routes
|
// Login routes
|
||||||
$group->get('/login', 'LoginControllerInstance:LoginPage')->setName('login');
|
$group->get('/login', '\Grocy\Controllers\LoginController:LoginPage')->setName('login');
|
||||||
$group->post('/login', 'LoginControllerInstance:ProcessLogin')->setName('login');
|
$group->post('/login', '\Grocy\Controllers\LoginController:ProcessLogin')->setName('login');
|
||||||
$group->get('/logout', 'LoginControllerInstance:Logout');
|
$group->get('/logout', '\Grocy\Controllers\LoginController:Logout');
|
||||||
|
|
||||||
// Generic entity interaction
|
// Generic entity interaction
|
||||||
$group->get('/userfields', '\Grocy\Controllers\GenericEntityController:UserfieldsList');
|
$group->get('/userfields', '\Grocy\Controllers\GenericEntityController:UserfieldsList');
|
||||||
|
@ -4,6 +4,8 @@ namespace Grocy\Services;
|
|||||||
|
|
||||||
class SessionService extends BaseService
|
class SessionService extends BaseService
|
||||||
{
|
{
|
||||||
|
const SESSION_COOKIE_NAME = 'grocy_session';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user