Files
oficial/app/src/Middleware/API.php

143 lines
5.5 KiB
PHP
Raw Normal View History

2023-11-25 00:55:31 -03:00
<?php
namespace Incoviba\Middleware;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;
2023-11-25 00:55:31 -03:00
use Incoviba\Exception\MissingAuthorizationHeader;
2024-03-20 23:07:49 -03:00
use Incoviba\Service;
2023-11-25 00:55:31 -03:00
class API
{
2024-07-26 23:57:04 -04:00
public function __construct(protected ResponseFactoryInterface $responseFactory,
protected LoggerInterface $logger,
protected Service\API $apiService,
2024-07-26 23:57:04 -04:00
protected Service\Login $loginService,
2025-05-12 16:01:09 -04:00
protected string $key,
2025-06-03 12:04:53 -04:00
array $apiUrls)
{
$this->permittedPaths = $apiUrls['permittedPaths'];
$this->simplePaths = $apiUrls['simplePaths'];
$this->externalPaths = $apiUrls['externalPaths'];
}
protected array $permittedPaths;
protected array $simplePaths;
protected array $externalPaths;
2023-11-25 00:55:31 -03:00
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
2025-05-12 16:01:09 -04:00
if ($this->validExternal($request)) {
return $handler->handle($request);
}
2023-11-25 00:55:31 -03:00
try {
$key = $this->apiService->getKey($request);
2025-06-03 12:04:53 -04:00
} catch (MissingAuthorizationHeader $exception) {
$this->logger->warning($exception, [
'headers' => $request->getHeaders()
]);
2023-11-25 00:55:31 -03:00
return $this->responseFactory->createResponse(401);
}
2024-07-26 23:57:04 -04:00
if ($this->validateSimpleKey($request, $key)) {
return $handler->handle($request);
}
2024-03-20 23:07:49 -03:00
if ($this->validate($request, $key)) {
2023-11-25 00:55:31 -03:00
return $handler->handle($request);
}
2025-06-03 12:06:35 -04:00
$this->logger->warning("Forbidden.", [
'headers' => $request->getHeaders()
]);
2023-11-25 00:55:31 -03:00
return $this->responseFactory->createResponse(403);
}
2024-03-20 23:07:49 -03:00
protected function validate(ServerRequestInterface $request, $incoming_key): bool
2023-11-25 00:55:31 -03:00
{
2024-07-26 23:57:04 -04:00
$selector = null;
$token = null;
2024-03-20 23:07:49 -03:00
if (str_contains($incoming_key, $this->loginService->getSeparator())) {
2024-07-26 23:57:04 -04:00
list($incoming_key, $selector, $token) = explode($this->loginService->getSeparator(), $incoming_key, 3);
if (!$this->loginService->isIn($selector, $token)) {
2024-03-20 23:07:49 -03:00
return false;
}
}
2024-07-26 23:57:04 -04:00
if (!$this->loginService->isIn($selector, $token) and !$this->validPermitted($request)) {
2024-03-20 23:07:49 -03:00
return false;
}
2023-11-25 00:55:31 -03:00
return $incoming_key === md5($this->key);
}
2024-07-26 23:57:04 -04:00
protected function validateSimpleKey(ServerRequestInterface $request, $incoming_key): bool
{
return $incoming_key === md5($this->key) and $this->noComplexKeyNeeded($request);
}
protected function noComplexKeyNeeded(ServerRequestInterface $request): bool
{
$uri = $request->getUri();
return in_array($uri->getPath(), $this->simplePaths);
2024-07-26 23:57:04 -04:00
}
2024-03-20 23:07:49 -03:00
protected function validPermitted(ServerRequestInterface $request): bool
{
$uri = $request->getUri();
return in_array($uri->getPath(), $this->permittedPaths);
2024-03-20 23:07:49 -03:00
}
2025-05-12 16:01:09 -04:00
protected function validExternal(ServerRequestInterface $request): bool
{
$uri = $request->getUri();
foreach ($this->externalPaths as $basePath => $paths) {
2025-05-12 16:35:33 -04:00
if (!str_starts_with($uri->getPath(), strtolower($basePath))) {
2025-05-12 16:01:09 -04:00
continue;
}
2025-05-12 16:35:33 -04:00
foreach ($paths as $subPath => $key) {
$fullPath = strtolower("{$basePath}{$subPath}");
2025-05-12 16:01:09 -04:00
if ($uri->getPath() === $fullPath) {
return $this->validateExternalKey($request, $basePath, $subPath);
}
}
}
return false;
}
protected function validateExternalKey(ServerRequestInterface $request, $basePath, $subPath): bool
{
$data = $this->externalPaths[$basePath][$subPath];
2025-05-29 19:43:06 -04:00
if (isset($data['validator'])) {
$method = [$data['validator'], 'validateToken'];
2025-05-30 14:18:48 -04:00
if ($method($request, $data)) {
2025-06-03 22:19:11 -04:00
$this->logger->info("Validated external key", [
'path' => $request->getUri()->getPath(),
'headers' => $request->getHeaders(),
'body' => $request->getBody()->getContents()
]);
2025-05-29 19:56:43 -04:00
return true;
}
2025-05-29 19:43:06 -04:00
}
if (isset($data['header']) and $request->hasHeader($data['header'])) {
$token = $request->getHeaderLine($data['header']);
if ($token === $this->externalPaths[$basePath][$subPath]['token']) {
return true;
}
}
2025-05-12 16:01:09 -04:00
if ($request->hasHeader('x-api-key')) {
$key = $request->getHeaderLine('x-api-key');
if ($key === $this->externalPaths[$basePath][$subPath]) {
return true;
}
}
if ($request->hasHeader('Authorization')) {
$key = $request->getHeaderLine('Authorization');
if (str_starts_with($key, 'Bearer ')) {
$key = substr($key, 7);
if ($key === $this->externalPaths[$basePath][$subPath]) {
return true;
}
}
}
2025-05-29 19:24:35 -04:00
$this->logger->warning("Failed to validate external key", [
'path' => $request->getUri()->getPath(),
'headers' => $request->getHeaders(),
2025-05-30 12:48:12 -04:00
'token' => $this->externalPaths[$basePath][$subPath],
'body' => $request->getBody()->getContents()
2025-05-29 19:24:35 -04:00
]);
2025-05-12 16:01:09 -04:00
return false;
}
2023-11-25 00:55:31 -03:00
}