PSR-15 Middleware for dealing with JWT generation and checks.
Status: Experimental. Not yet used in production, if interested take a look at the issues and feel welcome to make suggestions or open P/R :)
- PHP 7.1
- zend-expressive 3.0 (or any PSR-7 & PSR-15 compatible framework)
For zend-expressive 2.0 use the 0.3 release.
$ composer require soluble-wallit
Copy soluble-wallit.config.php.dist in your autoload directory.
cp ./vendor/soluble/wallit/config/soluble-wallit.config.php.dist ./config/autoload/soluble-wallit.config.local.php
Edit the config file and add your token keys
Ensure Soluble\Wallit\Config\ConfigProvider::class
is registered in the ./config/config.php
file.
<?php
use Zend\ConfigAggregator\ArrayProvider;
use Zend\ConfigAggregator\ConfigAggregator;
use Zend\ConfigAggregator\PhpFileProvider;
$cacheConfig = [
'config_cache_path' => 'data/config-cache.php',
];
$aggregator = new ConfigAggregator([
new ArrayProvider($cacheConfig),
// Register the Soluble Wallit ConfigProvider
Soluble\Wallit\Config\ConfigProvider::class,
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
new PhpFileProvider('config/development.config.php'),
], $cacheConfig['config_cache_path']);
return $aggregator->getMergedConfig();
To quickly browse the examples, see the smoke tests directory.
Create a PSR-15 handler to generate a JWT token upon successful authentication:
<?php declare(strict_types=1);
namespace App\Handler;
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
use Psr\Http\Server\RequestHandlerInterface;
use Fig\Http\Message\StatusCodeInterface;
use Ramsey\Uuid\Uuid;
use Soluble\Wallit\Service\JwtService;
use Soluble\Wallit\Token\Jwt\JwtClaims;
use Zend\Diactoros\Response\JsonResponse;
class AuthHandler implements RequestHandlerInterface
{
/**
* @var JwtService
*/
protected $jwtService;
public function __construct(JwtService $jwtService)
{
$this->jwtService = $jwtService;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$method = $request->getMethod();
if ($method !== 'POST') {
throw new \RuntimeException('TODO - Handle error your way ;)');
}
$body = $request->getParsedBody();
$login = $body['login'] ?? '';
$password = $body['password'] ?? '';
if ($login === 'demo' && $password === 'demo') {
$token = $this->jwtService->createToken([
JwtClaims::ID => Uuid::uuid1(),
'login' => $login
]);
return new JsonResponse([
'access_token' => (string) $token,
'token_type' => 'example',
]);
}
return (new JsonResponse([
'success' => false
]))->withStatus(StatusCodeInterface::STATUS_UNAUTHORIZED);
}
}
Its related factory can be:
<?php declare(strict_types=1);
namespace App\Handler;
use Psr\Container\ContainerInterface;
use Soluble\Wallit\Service\JwtService;
class AuthHandlerFactory
{
public function __invoke(ContainerInterface $container): AuthHandler
{
return new AuthHandler(
$container->get(JwtService::class)
);
}
}
Add a route in ./config/routes.php
<?php
//....
$app->post('/auth', App\Handler\AuthHandler::class, 'auth');
Simply pipe or add the JwtAuthMiddleware::class
to the desired route.
As an example in the ./config/routes.php
file :
<?php declare(strict_types=1);
use Soluble\Wallit\Middleware\JwtAuthMiddleware;
// ...
$app->get('/admin', [
JwtAuthMiddleware::class,
App\Handler\AdminHandler::class
], 'admin');
The token is available as a request attribute: $request->getAttribute(JwtAuthMiddleware::class)
.
<?php declare(strict_types=1);
namespace App\Handler;
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
use Psr\Http\Server\RequestHandlerInterface;
use Soluble\Wallit\Middleware\JwtAuthMiddleware;
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Expressive\Template\TemplateRendererInterface;
use Lcobucci\JWT\Token;
class AdminHandler implements RequestHandlerInterface
{
/**
* @var TemplateRendererInterface
*/
private $template;
public function __construct(TemplateRendererInterface $template) {
$this->template = $template;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$token = $this->getTokenFromRequest($request);
return new HtmlResponse($this->template->render('pages::admin', [
'token' => $token,
'login' => $token->getClaim('login')
]));
}
protected function getTokenFromRequest(ServerRequestInterface $request): Token
{
return $request->getAttribute(JwtAuthMiddleware::class);
}
}
- fig/http-message-util Utility classes and constants for use with PSR-7 (psr/http-message)
- psr/http-message Common interface for HTTP messages (PHP FIG PSR-7)
- psr/container Common Container Interface (PHP FIG PSR-11)
- PSR 4 Autoloader
- PSR 2 Coding Style Guide