kuick / security
Kuick Security is a package for security related tasks. Includes PSR-15 middleware implementation
Requires
- php: >=8.2.0
- kuick/http: ^1.0|^2.0
- psr/log: ^3.0
Requires (Dev)
- kuick/qa-toolkit: ^2.0
Provides
README
Security package implementing PSR-15 middleware
Key features
- PSR-15(https://www.php-fig.org/psr/psr-15/) security middleware implementation
- Support for flexible Guards (any callable)
- Guardhouse service with methods to register Guards (regex path support)
Installation
composer require kuick/security
Usage
1. Create a guard
A guard is any invokable object (or closure) accepting a ServerRequestInterface and returning void|null.
Throw a Kuick\Http\HttpException to deny the request.
use Kuick\Http\HttpException; use Kuick\Http\Message\Response; use Psr\Http\Message\ServerRequestInterface; class BearerTokenGuard { public function __invoke(ServerRequestInterface $request): void { $authHeader = $request->getHeaderLine('Authorization'); if (!str_starts_with($authHeader, 'Bearer valid-token')) { throw new HttpException(Response::HTTP_UNAUTHORIZED, 'Invalid or missing token'); } } }
2. Register guards in the Guardhouse
Use addGuard(string $path, object $guard, array $methods = [...]) to register guards.
The $path is a full regex (anchored as #^…$#). Named capture groups are merged into the request's query params.
By default (when $methods is omitted), a guard matches all HTTP methods: GET, POST, PUT, PATCH, DELETE, OPTIONS. HEAD is automatically included whenever GET is listed.
use Kuick\Security\Guardhouse; use Psr\Log\NullLogger; $guardhouse = (new Guardhouse(new NullLogger())) // protect all routes with a token check ->addGuard('/api/.*', new BearerTokenGuard()) // restrict a specific route to GET only ->addGuard('/api/resource/(?P<id>\d+)', new BearerTokenGuard(), ['GET']);
3. Wire up the PSR-15 middleware
Pass the Guardhouse to SecurityMiddleware and add it to your PSR-15 middleware stack.
use Kuick\Security\SecurityMiddleware; $middleware = new SecurityMiddleware($guardhouse, new NullLogger()); // Example with any PSR-15-compatible dispatcher (e.g. Relay, Slim, etc.) $response = $middleware->process($serverRequest, $nextHandler);
If a guard throws a Kuick\Http\HttpException the exception propagates up — your framework's error handler is responsible for converting it into an HTTP response. If all guards pass, the request is forwarded to $nextHandler.
Path regex & captured parameters
Regex captures (named or positional) from the matched path are merged into the request's query params before the guard is invoked:
// Guard registered for: '/users/(?<userId>\d+)' // Request: GET /users/42 // Inside the guard, $request->getQueryParams()['userId'] === '42'