mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-14 04:00:57 +03:00
Converted MissingAuthenticationException into a problem details exception
This commit is contained in:
parent
f502eb0195
commit
6f4e5175da
8 changed files with 48 additions and 57 deletions
|
@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shlinkio\Shlink\Rest\Authentication;
|
||||
|
||||
use Psr\Container;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Shlinkio\Shlink\Rest\Exception\NoAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_reduce;
|
||||
|
@ -30,13 +29,12 @@ class RequestToHttpAuthPlugin implements RequestToHttpAuthPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @throws Container\ContainerExceptionInterface
|
||||
* @throws NoAuthenticationException
|
||||
* @throws MissingAuthenticationException
|
||||
*/
|
||||
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface
|
||||
{
|
||||
if (! $this->hasAnySupportedHeader($request)) {
|
||||
throw NoAuthenticationException::fromExpectedTypes(self::SUPPORTED_AUTH_HEADERS);
|
||||
throw MissingAuthenticationException::fromExpectedTypes(self::SUPPORTED_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
return $this->authPluginManager->get($this->getFirstAvailableHeader($request));
|
||||
|
|
|
@ -4,15 +4,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shlinkio\Shlink\Rest\Authentication;
|
||||
|
||||
use Psr\Container;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Shlinkio\Shlink\Rest\Exception\NoAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
|
||||
|
||||
interface RequestToHttpAuthPluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws Container\ContainerExceptionInterface
|
||||
* @throws NoAuthenticationException
|
||||
* @throws MissingAuthenticationException
|
||||
*/
|
||||
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface;
|
||||
}
|
||||
|
|
36
module/Rest/src/Exception/MissingAuthenticationException.php
Normal file
36
module/Rest/src/Exception/MissingAuthenticationException.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Rest\Exception;
|
||||
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Zend\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
|
||||
use Zend\ProblemDetails\Exception\ProblemDetailsExceptionInterface;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
class MissingAuthenticationException extends RuntimeException implements ProblemDetailsExceptionInterface
|
||||
{
|
||||
use CommonProblemDetailsExceptionTrait;
|
||||
|
||||
private const TITLE = 'Invalid authorization';
|
||||
public const TYPE = 'INVALID_AUTHORIZATION';
|
||||
|
||||
public static function fromExpectedTypes(array $expectedTypes): self
|
||||
{
|
||||
$e = new self(sprintf(
|
||||
'Expected one of the following authentication headers, but none were provided, ["%s"]',
|
||||
implode('", "', $expectedTypes)
|
||||
));
|
||||
|
||||
$e->detail = $e->getMessage();
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_UNAUTHORIZED;
|
||||
$e->additional = ['expectedTypes' => $expectedTypes];
|
||||
|
||||
return $e;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Rest\Exception;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
class NoAuthenticationException extends RuntimeException
|
||||
{
|
||||
public static function fromExpectedTypes(array $expectedTypes): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'None of the valid authentication mechanisms where provided. Expected one of ["%s"]',
|
||||
implode('", "', $expectedTypes)
|
||||
));
|
||||
}
|
||||
}
|
|
@ -6,24 +6,19 @@ namespace Shlinkio\Shlink\Rest\Middleware;
|
|||
|
||||
use Fig\Http\Message\RequestMethodInterface;
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
|
||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPluginInterface;
|
||||
use Shlinkio\Shlink\Rest\Exception\NoAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Expressive\Router\RouteResult;
|
||||
|
||||
use function Functional\contains;
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterface, RequestMethodInterface
|
||||
{
|
||||
|
@ -44,16 +39,6 @@ class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterfa
|
|||
$this->logger = $logger ?: new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
*
|
||||
* @return Response
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function process(Request $request, RequestHandlerInterface $handler): Response
|
||||
{
|
||||
/** @var RouteResult|null $routeResult */
|
||||
|
@ -67,15 +52,7 @@ class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterfa
|
|||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
try {
|
||||
$plugin = $this->requestToAuthPlugin->fromRequest($request);
|
||||
} catch (ContainerExceptionInterface | NoAuthenticationException $e) {
|
||||
$this->logger->warning('Invalid or no authentication provided. {e}', ['e' => $e]);
|
||||
return $this->createErrorResponse(sprintf(
|
||||
'Expected one of the following authentication headers, but none were provided, ["%s"]',
|
||||
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS)
|
||||
));
|
||||
}
|
||||
$plugin = $this->requestToAuthPlugin->fromRequest($request);
|
||||
|
||||
try {
|
||||
$plugin->verify($request);
|
||||
|
|
|
@ -28,7 +28,8 @@ class RestUtils
|
|||
|
||||
public const INVALID_CREDENTIALS_ERROR = 'INVALID_CREDENTIALS';
|
||||
public const INVALID_AUTH_TOKEN_ERROR = 'INVALID_AUTH_TOKEN';
|
||||
public const INVALID_AUTHORIZATION_ERROR = 'INVALID_AUTHORIZATION';
|
||||
/** @deprecated */
|
||||
public const INVALID_AUTHORIZATION_ERROR = Rest\MissingAuthenticationException::TYPE;
|
||||
public const INVALID_API_KEY_ERROR = 'INVALID_API_KEY';
|
||||
|
||||
/** @deprecated */
|
||||
|
|
|
@ -11,7 +11,7 @@ use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
|
|||
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
|
||||
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthorizationHeaderPlugin;
|
||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
|
||||
use Shlinkio\Shlink\Rest\Exception\NoAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
|
||||
use function implode;
|
||||
|
@ -35,7 +35,7 @@ class RequestToAuthPluginTest extends TestCase
|
|||
{
|
||||
$request = new ServerRequest();
|
||||
|
||||
$this->expectException(NoAuthenticationException::class);
|
||||
$this->expectException(MissingAuthenticationException::class);
|
||||
$this->expectExceptionMessage(sprintf(
|
||||
'None of the valid authentication mechanisms where provided. Expected one of ["%s"]',
|
||||
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS)
|
||||
|
|
|
@ -19,7 +19,7 @@ use Shlinkio\Shlink\Rest\Action\AuthenticateAction;
|
|||
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
|
||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
|
||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPluginInterface;
|
||||
use Shlinkio\Shlink\Rest\Exception\NoAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
|
||||
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
|
@ -128,7 +128,7 @@ class AuthenticationMiddlewareTest extends TestCase
|
|||
};
|
||||
|
||||
yield 'container exception' => [$containerException];
|
||||
yield 'authentication exception' => [NoAuthenticationException::fromExpectedTypes([])];
|
||||
yield 'authentication exception' => [MissingAuthenticationException::fromExpectedTypes([])];
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
|
Loading…
Add table
Reference in a new issue