Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save geerteltink/0caae7d60ea2a5a141696339b6edaf56 to your computer and use it in GitHub Desktop.

Select an option

Save geerteltink/0caae7d60ea2a5a141696339b6edaf56 to your computer and use it in GitHub Desktop.
PSR-7 Security Middleware (Authentication / Authorization)
<?php
namespace App\Core\Security;
use App\Domain\User\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use PSR7Session\Http\SessionMiddleware;
class AuthenticationMiddleware
{
private $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
{
$user = null;
// Get user from session
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
if ($id = $session->get('uid')) {
// Get user from Repository
$user = $this->userRepository->find((int) $id);
if (!$user) {
// Invalid user id claim, remove it
$session->remove('uid');
}
}
$token = new SecurityToken($user);
return $next($request->withAttribute(SecurityTokenInterface::class, $token), $response);
}
}
<?php
namespace App\Core\Security;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\RedirectResponse;
class AuthorizationMiddleware
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
{
$security = $request->getAttribute(SecurityTokenInterface::class);
$level = $request->getAttribute('_security_level');
if ($level && !$security->isGranted($level)) {
if ($security->isAuthenticated()) {
return $response->withStatus(403);
}
// Redirect to login
return new RedirectResponse('/login');
}
return $next($request, $response);
}
}
<?php
namespace App\Core\Security;
use App\Domain\User\Role;
use App\Domain\User\User;
class SecurityToken implements SecurityTokenInterface
{
private $user;
private $roles = [Role::ANONYMOUS];
/**
* @inheritdoc
*/
public function __construct(User $user = null)
{
if ($user) {
$this->user = $user;
$this->roles = [Role::USER];
if ($user->isEmailConfirmed()) {
$this->roles[] = Role::REGISTERED;
}
if ($user->isAdmin()) {
$this->roles[] = Role::ADMIN;
}
}
}
/**
* @inheritdoc
*/
public function isGranted(string $role)
{
return in_array($role, $this->roles, true);
}
/**
* @inheritdoc
*/
public function isAuthenticated()
{
return null !== $this->user;
}
/**
* @inheritdoc
*/
public function getName()
{
if ($this->user) {
return $this->user->getName();
}
return 'annon.';
}
/**
* @inheritdoc
*/
public function getUser()
{
return $this->user;
}
}
<?php
namespace App\Core\Security;
use App\Domain\User\User;
interface SecurityTokenInterface
{
/**
* @param User|null $user
*/
public function __construct(User $user = null);
/**
* @param string $role
*
* @return bool
*/
public function isGranted(string $role);
/**
* @return bool
*/
public function isAuthenticated();
/**
* @return null|string
*/
public function getName();
/**
* @return null|User
*/
public function getUser();
}
<?php
use Zend\Expressive;
return [
'dependencies' => [
'factories' => [
Expressive\Helper\ServerUrlMiddleware::class => Expressive\Helper\ServerUrlMiddlewareFactory::class,
Expressive\Helper\UrlHelperMiddleware::class => Expressive\Helper\UrlHelperMiddlewareFactory::class,
PSR7Session\Http\SessionMiddleware::class => App\Core\Factory\SessionMiddlewareFactory::class,
App\Core\Security\AuthenticationMiddleware::class => App\Core\Security\AuthenticationMiddlewareFactory::class,
],
],
'middleware_pipeline' => [
'always' => [
'middleware' => [
PSR7Session\Http\SessionMiddleware::class,
Expressive\Helper\ServerUrlMiddleware::class,
],
'priority' => 10000,
],
'routing' => [
'middleware' => [
Expressive\Container\ApplicationFactory::ROUTING_MIDDLEWARE,
Expressive\Helper\UrlHelperMiddleware::class,
App\Core\Security\AuthenticationMiddleware::class,
App\Core\Security\AuthorizationMiddleware::class,
Expressive\Container\ApplicationFactory::DISPATCH_MIDDLEWARE,
],
'priority' => 1,
],
'error' => [
'middleware' => [
],
'error' => true,
'priority' => -10000,
],
],
];
<?php
use App\Domain\User\Role;
$locales = '{locale:en|nl|de|fr|es}';
return [
'routes' => [
[
'name' => 'frontend.index',
'path' => '/[' . $locales . ']',
'middleware' => App\Frontend\Action\HomePageAction::class,
'allowed_methods' => ['GET'],
],
[
'name' => 'admin.dashboard',
'path' => '/admin',
'middleware' => App\Backend\Action\DashboardAction::class,
'allowed_methods' => ['GET'],
'options' => [
'defaults' => [
'_security_level' => Role::ADMIN,
],
],
],
],
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment