dasprid / helios
PSR-7 authentication middleware
Requires
- php: ^7.1
- cultuurnet/clock: ^1.0
- dasprid/pikkuleipa: ^2.0
- dasprid/treereader: ^1.1
- psr/http-message: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- phpunit/phpunit: ^5.5
- psr/container: ^1.0
- squizlabs/php_codesniffer: ^2.7
- zendframework/zend-diactoros: ^1.3
Suggests
- psr/container: For using the supplied factories
README
Helios is an authentication middleware embracing PSR-7. It's purpose is to keep the identity completely request dependent, as well as avoiding the use of server-side session through the use of JSON Web Tokens.
Installation
Install via composer:
$ composer require dasprid/helios
Getting started (for Expressive)
JWT cookies
This library uses Pikkuleipa, a cookie manager utilizing JSON Web Tokens. In order to start working with Helios, you need to configure Pikkuleipa first.
Import the factory config
Create a file named helios.global.php
or similar in your autoloading config directory:
<?php return (new DASPRiD\Helios\ConfigProvider())->__invoke();
This will introduce a few factories, namely you can retrieve the following objects through that:
DASPRiD\Helios\IdentityCookieManager
throughDASPRiD\Helios\IdentityCookieManager
DASPRiD\Helios\IdentityMiddleware
throughDASPRiD\Helios\IdentityMiddleware
Create an identity lookup
You'll need to implement a lookup which retrieves the user identity based on the subject stored in the token. Register that lookup in your dependency container:
<?php use DASPRiD\Helios\Identity\IdentityLookupInterface; use DASPRiD\Helios\Identity\LookupResult; class MyIdentityLookup implements IdentityLookupInterface { public function lookup($subject) : LookupResult { // Pseudo-code here if ($this->repository->has($subject)) { return LookupResult::fromIdentity($this->repository->get($subject)); } return LookupResult::invalid(); } }
Then wire your implementation to Helios by updating configuration file:
<?php return [ 'helios' => [ // ... 'identity_lookup_id' => MyIdentityLookup::class, ], ];
Configure Helios
For Helios to function, it needs a few configuration variables. Copy the file doc/example-config.php
and adjust the
values as needed.
Register the identity middleware
Helios ships with an IdentityMiddleware
, which should be registered in your middleware pipeline before the dispatch
middleware. The exact location in the stack depends on your own needs.
Write your sign-in middleware
Helios itself does not ship with any actual logic for signing users in or out. Thus, a simple sign-in middleware may look like this:
<?php class MySignIn { /** * @var \DASPRiD\Helios\IdentityCookieManager */ private $identityCookieManager; public function __invoke() { // Verify the user if ($userIsValid) { $response = new Zend\Diactoros\Response\RedirectResponse('/go/somewhere'); return $this->identityCookieManager->injectCookie( $response, $user->getId(), ! $rememberMeSelected ); } // Do some error response here } }
Write your sign-out middleware
Similar to the sign-in middleware, your sign-out middleware can use the IdentityCookieManager
to invalidate the
cookie:
<?php class MySignOut { /** * @var \DASPRiD\Helios\IdentityCookieManager */ private $identityCookieManager; public function __invoke() { $response = new Zend\Diactoros\Response\RedirectResponse('/go/somewhere'); return $this->identityCookieManager->expireCookie($response); } }
Retrieve the user identity in a middleware
Each time the user is retrieved by the IdentityMiddleware
, it is injected into the request as an attribute. Thus when
you need the user in your middleware, you can easily get it:
<?php use DASPRiD\Helios\IdentityMiddleware; use Psr\Http\Message\ServerRequestInterface; class SomeOtherMiddleware { public function __invoke(ServerRequestInterface $request) { $user = $request->getAttribute(IdentityMiddleware::IDENTITY_ATTRIBUTE); } }
Sometimes it may be required that the identity is always available in your view, e.g. to display the username in the layout. The proper way to handle that case is to use a specific template renderer which takes the request object, beside the usual view parameters, and injects the user into the view variables before rendering. Try to avoid injecting the entire request object into the view parameters though.