Verify X-Auth bearers in any PSR-15-compatible PHP framework — Laravel, Slim, Symfony, Mezzio.
Pull the SDK from Packagist.
composer require xentranet/x-authBuild the SDK once and resolve it from your container.
<?php
declare(strict_types=1);
namespace App;
use Xentranet\XAuth\XAuth;
final class XAuthFactory
{
public static function create(): XAuth
{
return new XAuth([
'tenant_id' => getenv('XAUTH_TENANT_ID'),
]);
}
}Implement MiddlewareInterface and short-circuit with 401 on a missing or mismatched bearer.
<?php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Xentranet\XAuth\XAuth;
final class VerifyTransaction implements MiddlewareInterface
{
public function __construct(
private XAuth $xauth,
private string $action,
) {}
public function process(ServerRequestInterface $req, RequestHandlerInterface $next): ResponseInterface
{
$bearer = str_replace('Bearer ', '', $req->getHeaderLine('Authorization'));
try {
$ctx = $this->xauth->verify($bearer, [
'expect' => ['action' => $this->action],
]);
return $next->handle($req->withAttribute('transaction_ctx', $ctx));
} catch (\Throwable $e) {
return new \Nyholm\Psr7\Response(401, [], 'invalid_transaction');
}
}
}Register the middleware on any sensitive endpoint. The handler can read the bound transaction_ctx off the request attributes.
<?php
$app->post('/api/transfer', function ($req, $res) {
$ctx = $req->getAttribute('transaction_ctx');
$ledger->transfer($ctx);
$res->getBody()->write('{"ok":true}');
return $res;
})->add(new VerifyTransaction($container->get(XAuth::class), 'transfer'));