mirror of
https://github.com/grocy/grocy.git
synced 2026-03-28 15:49:25 +01:00
Consider the case where a Grocy user wants to use reverse proxy authentication OR authentication with an API key. By default, authenticating reverse proxy will unconditionally perform user authentication, before allowing a request to be passed to Grocy which will verify an API key, rendering them virtually useless. So the proxy needs to be configured not to perform authentication in certain cases, for example the presence of the `Grocy-Api-Key` HTTP header, or the path being a subdirectory of `/api/`. It can however be tricky to configure this though. For example, nginx does not allow conditional authentication, or conditional header setting. In those cases, when the condition is met, the username header would still be returned, albeit empty. Grocy will then create an user with empty username (not normally possible). It default to having all permissions, and while most are removable, reading chores/stock/etc. do not seem to be, and would thus be public. This returns an error when the username is empty, to accomodate for those cases.
70 lines
1.9 KiB
PHP
70 lines
1.9 KiB
PHP
<?php
|
|
|
|
namespace Grocy\Middleware;
|
|
|
|
use Grocy\Services\DatabaseService;
|
|
use Grocy\Services\UsersService;
|
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
|
|
class ReverseProxyAuthMiddleware extends AuthMiddleware
|
|
{
|
|
public function authenticate(Request $request)
|
|
{
|
|
define('GROCY_EXTERNALLY_MANAGED_AUTHENTICATION', true);
|
|
|
|
$db = DatabaseService::getInstance()->GetDbConnection();
|
|
|
|
// API key authentication is also ok
|
|
$auth = new ApiKeyAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
|
$user = $auth->authenticate($request);
|
|
if ($user !== null)
|
|
{
|
|
return $user;
|
|
}
|
|
|
|
if (GROCY_REVERSE_PROXY_AUTH_USE_ENV)
|
|
{
|
|
if (!isset($_SERVER[GROCY_REVERSE_PROXY_AUTH_HEADER]))
|
|
{
|
|
// Variable is not set
|
|
throw new \Exception('ReverseProxyAuthMiddleware: ' . GROCY_REVERSE_PROXY_AUTH_HEADER . ' env variable is missing (could not be found in $_SERVER array)');
|
|
}
|
|
|
|
$username = $_SERVER[GROCY_REVERSE_PROXY_AUTH_HEADER];
|
|
if (strlen($username) === 0)
|
|
{
|
|
// Variable is empty
|
|
throw new \Exception('ReverseProxyAuthMiddleware: ' . GROCY_REVERSE_PROXY_AUTH_HEADER . ' env variable is invalid');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$username = $request->getHeader(GROCY_REVERSE_PROXY_AUTH_HEADER);
|
|
if (count($username) !== 1)
|
|
{
|
|
// Invalid configuration of Proxy
|
|
throw new \Exception('ReverseProxyAuthMiddleware: ' . GROCY_REVERSE_PROXY_AUTH_HEADER . ' header is missing');
|
|
}
|
|
$username = $username[0];
|
|
if (strlen($username) === 0)
|
|
{
|
|
// Header is empty
|
|
throw new \Exception('ReverseProxyAuthMiddleware: ' . GROCY_REVERSE_PROXY_AUTH_HEADER . ' header is invalid');
|
|
}
|
|
}
|
|
|
|
$user = $db->users()->where('username', $username)->fetch();
|
|
if ($user == null)
|
|
{
|
|
$user = UsersService::getInstance()->CreateUser($username, '', '', '');
|
|
}
|
|
|
|
return $user;
|
|
}
|
|
|
|
public static function ProcessLogin(array $postParams)
|
|
{
|
|
throw new \Exception('Not implemented');
|
|
}
|
|
}
|