Fixed special purpose API Keys authentication (fixes #2976)

This commit is contained in:
Bernd Bestel 2026-08-29 20:09:17 +02:00
parent 79db4bfbe7
commit d9889fd157
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
5 changed files with 74 additions and 14 deletions

View File

@ -0,0 +1,57 @@
> ⚠️ xxxBREAKING CHANGESxxx
> ❗ xxxImportant upgrade informationXXX
> 💡 xxxMinor upgrade informationXXX
### New Feature: xxxx
- xxx
### Stock
- xxx
### Shopping list
- xxx
### Recipes
- xxx
### Meal plan
- xxx
### Chores
- xxx
### Calendar
- Fixed that the iCal export was broken (any shared `https://<Grocy>/api/calendar/ical?secret=xxx`-link always returned `401 Unauthorized`)
### Tasks
- xxx
### Batteries
- xxx
### Equipment
- xxx
### Userfields
- xxx
### General
- xxx
### API
- xxx

View File

@ -40,7 +40,7 @@ class ApiKeyAuthMiddleware extends BaseAuthMiddleware
// Handling of special purpose API keys
if (!$validApiKey)
{
if ($this->RouteName === 'calendar-ical')
if ($this->GetRouteName($request) === 'calendar-ical')
{
if ($request->getQueryParam('secret') !== null && $apiKeyService->IsValidApiKey($request->getQueryParam('secret'), ApiKeyService::API_KEY_TYPE_SPECIAL_PURPOSE_CALENDAR_ICAL))
{

View File

@ -11,17 +11,10 @@ use Slim\Routing\RouteContext;
abstract class BaseAuthMiddleware extends BaseMiddleware
{
protected ?string $RouteName = null;
protected bool $IsApiRoute = false;
public function __invoke(Request $request, RequestHandler $handler): Response
{
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$this->RouteName = $route->getName();
$this->IsApiRoute = string_starts_with($request->getUri()->getPath(), '/api/');
if ($this->RouteName === 'root' || $this->RouteName === 'login')
$routeName = $this->GetRouteName($request);
if ($routeName === 'root' || $routeName === 'login')
{
// Root and Login routes are public/unauthenticated
@ -53,7 +46,7 @@ abstract class BaseAuthMiddleware extends BaseMiddleware
define('GROCY_AUTHENTICATED', false);
$response = $this->ResponseFactory->createResponse();
if ($this->IsApiRoute)
if ($this->IsApiRoute($request))
{
return $response->withStatus(401);
}
@ -69,7 +62,7 @@ abstract class BaseAuthMiddleware extends BaseMiddleware
define('GROCY_USER_USERNAME', $user->username);
define('GROCY_USER_PICTURE_FILE_NAME', $user->picture_file_name);
return $response = $handler->handle($request);
return $handler->handle($request);
}
}
}
@ -122,6 +115,16 @@ abstract class BaseAuthMiddleware extends BaseMiddleware
}
}
protected function GetRouteName(Request $request): ?string
{
return RouteContext::fromRequest($request)->getRoute()?->getName();
}
protected function IsApiRoute(Request $request): bool
{
return string_starts_with($request->getUri()->getPath(), '/api/');
}
/**
* @param array $postParams
* @return bool True/False if the provided credentials were valid

View File

@ -10,7 +10,7 @@ class DefaultAuthMiddleware extends BaseAuthMiddleware
{
protected function AuthenticateRequest(Request $request)
{
if ($this->IsApiRoute)
if ($this->IsApiRoute($request))
{
// Session cookie or API Key is ok
$auth = new SessionAuthMiddleware($this->AppContainer, $this->ResponseFactory);

View File

@ -13,7 +13,7 @@ class ReverseProxyAuthMiddleware extends BaseAuthMiddleware
define('GROCY_EXTERNALLY_MANAGED_AUTHENTICATION', true);
// Try to use regular API Key authentication (applies when the reverse proxy is configured to be bypassed for API routes)
if ($this->IsApiRoute)
if ($this->IsApiRoute($request))
{
$auth = new ApiKeyAuthMiddleware($this->AppContainer, $this->ResponseFactory);
$user = $auth->AuthenticateRequest($request);