77 lines
2.4 KiB
PHP
77 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace NoccyLabs\Mercureact\Http\Middleware;
|
|
|
|
use NoccyLabs\Mercureact\Configuration;
|
|
use NoccyLabs\Mercureact\Exception\SecurityException;
|
|
use NoccyLabs\SimpleJWT\JWTToken;
|
|
use NoccyLabs\SimpleJWT\Key\JWTPlaintextKey;
|
|
use NoccyLabs\SimpleJWT\Validator\JWTValidator;
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
use React\Promise\Promise;
|
|
use React\Promise\PromiseInterface;
|
|
|
|
class SecurityMiddleware
|
|
{
|
|
|
|
public function __construct(
|
|
private Configuration $config
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @param ServerRequestInterface $request
|
|
* @param callable $next
|
|
* @return PromiseInterface
|
|
*/
|
|
public function __invoke(ServerRequestInterface $request, callable $next): PromiseInterface
|
|
{
|
|
return new Promise(
|
|
function (callable $resolve, callable $reject) use ($request, $next) {
|
|
// Check JWT in authorization header or authorization query param
|
|
$request = $this->checkAuthorization($request);
|
|
|
|
$resolve($next($request));
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check authorization and return a new request with added attributes:
|
|
*
|
|
* 'authorization' => JWTToken
|
|
*
|
|
* @param ServerRequestInterface $request
|
|
* @return ServerRequestInterface
|
|
*/
|
|
private function checkAuthorization(ServerRequestInterface $request): ServerRequestInterface
|
|
{
|
|
$authorization = $request->getHeaderLine('authorization');
|
|
if (str_starts_with(strtolower($authorization), "bearer ")) {
|
|
$jwt = substr($authorization, strpos($authorization, " ")+1);
|
|
$key = new JWTPlaintextKey($this->config->getJwtSecret());
|
|
$tok = new JWTToken($key, $jwt);
|
|
if (!$tok->isValid()) {
|
|
throw new SecurityException(
|
|
message: "Invalid token",
|
|
code: SecurityException::ERR_ACCESS_DENIED
|
|
);
|
|
}
|
|
$claims = $tok->claims->getAll()['mercure']??[];
|
|
return $request
|
|
->withAttribute('mercure.publish', $claims['publish']??[])
|
|
->withAttribute('mercure.subscribe', $claims['subscribe']??[])
|
|
->withAttribute('mercure.payload', $claims['payload']??[])
|
|
->withAttribute('authorized', true);
|
|
} else {
|
|
return $request
|
|
->withAttribute('authorized', false);
|
|
|
|
}
|
|
}
|
|
|
|
} |