Created system of authentication plugins

This commit is contained in:
Alejandro Celaya
2018-09-28 22:08:01 +02:00
parent e88468d867
commit 8e61639598
18 changed files with 675 additions and 242 deletions

View File

@@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication\Plugin;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Authentication\JWTServiceInterface;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Util\RestUtils;
use Throwable;
use Zend\I18n\Translator\TranslatorInterface;
use function count;
use function explode;
use function sprintf;
use function strtolower;
class AuthorizationHeaderPlugin implements AuthenticationPluginInterface
{
public const HEADER_NAME = 'Authorization';
/**
* @var JWTServiceInterface
*/
private $jwtService;
/**
* @var TranslatorInterface
*/
private $translator;
public function __construct(JWTServiceInterface $jwtService, TranslatorInterface $translator)
{
$this->jwtService = $jwtService;
$this->translator = $translator;
}
/**
* @throws VerifyAuthenticationException
*/
public function verify(ServerRequestInterface $request): void
{
// Get token making sure the an authorization type is provided
$authToken = $request->getHeaderLine(self::HEADER_NAME);
$authTokenParts = explode(' ', $authToken);
if (count($authTokenParts) === 1) {
throw VerifyAuthenticationException::withError(
RestUtils::INVALID_AUTHORIZATION_ERROR,
sprintf(
$this->translator->translate('You need to provide the Bearer type in the %s header.'),
self::HEADER_NAME
)
);
}
// Make sure the authorization type is Bearer
[$authType, $jwt] = $authTokenParts;
if (strtolower($authType) !== 'bearer') {
throw VerifyAuthenticationException::withError(
RestUtils::INVALID_AUTHORIZATION_ERROR,
sprintf($this->translator->translate(
'Provided authorization type %s is not supported. Use Bearer instead.'
), $authType)
);
}
try {
if (! $this->jwtService->verify($jwt)) {
throw $this->createInvalidTokenError();
}
} catch (Throwable $e) {
throw $this->createInvalidTokenError($e);
}
}
private function createInvalidTokenError(Throwable $prev = null): VerifyAuthenticationException
{
return VerifyAuthenticationException::withError(
RestUtils::INVALID_AUTH_TOKEN_ERROR,
sprintf($this->translator->translate(
'Missing or invalid auth token provided. Perform a new authentication request and send provided '
. 'token on every new request on the %s header'
), self::HEADER_NAME),
$prev
);
}
public function update(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$authToken = $request->getHeaderLine(self::HEADER_NAME);
[, $jwt] = explode(' ', $authToken);
$jwt = $this->jwtService->refresh($jwt);
return $response->withHeader(self::HEADER_NAME, sprintf('Bearer %s', $jwt));
}
}