Skip to content

Instantly share code, notes, and snippets.

@CauanCabral
Last active July 3, 2020 16:11
Show Gist options
  • Save CauanCabral/27bdb295f7854116e875e4b0c4471289 to your computer and use it in GitHub Desktop.
Save CauanCabral/27bdb295f7854116e875e4b0c4471289 to your computer and use it in GitHub Desktop.
CakePHP 4.1 Application Sample with Authentication and Authorization middlewares
<?php
namespace App\Controller;
class AppController extends Controller
{
/**
* Initialization hook method.
*
* Use this method to add common initialization code like loading components.
*
* @return void
*/
public function initialize(): void
{
$this->loadComponent('Authentication.Authentication');
$this->loadComponent('Authorization.Authorization');
// Code continue
}
}
<?php
namespace App;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Authorization\AuthorizationService;
use Authorization\AuthorizationServiceInterface;
use Authorization\AuthorizationServiceProviderInterface;
use Authorization\Middleware\AuthorizationMiddleware;
use Authorization\Middleware\RequestAuthorizationMiddleware;
use Authorization\Policy\MapResolver;
use Authorization\Policy\OrmResolver;
use Authorization\Policy\ResolverCollection;
use Cake\Core\Configure;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\BaseApplication;
use Cake\Http\Middleware\BodyParserMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\Http\ServerRequest;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use CakeDC\Auth\Policy\RbacPolicy;
use CakeDC\Auth\Rbac\Rbac;
use Psr\Http\Message\ServerRequestInterface;
/**
* Application setup class.
*
* This defines the bootstrapping logic and middleware layers you
* want to use in your application.
*/
class Application extends BaseApplication implements AuthenticationServiceProviderInterface, AuthorizationServiceProviderInterface
{
/**
* Local instance of Rbac
*
* @var \CakeDC\Auth\Rbac\Rbac|null
*/
protected $rbacInstance = null;
/**
* {@inheritDoc}
*/
public function bootstrap(): void
{
parent::bootstrap();
if (PHP_SAPI === 'cli') {
$this->bootstrapCli();
}
$this->addPlugin('CakeDC/Auth', ['bootstrap' => false]);
$this->addOptionalPlugin(\DebugKit\Plugin::class);
}
/**
* Setup the middleware queue your application will use.
*
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
* @return \Cake\Http\MiddlewareQueue The updated middleware queue.
*/
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime')
]))
->add(new RoutingMiddleware($this, '_cake_routes_'))
->add(new EncryptedCookieMiddleware(['CookieAuth'], Configure::read('Security.cipher')))
->add(new BodyParserMiddleware())
->add(new AuthenticationMiddleware($this))
->add(new AuthorizationMiddleware($this, [
'requireAuthorizationCheck' => true,
'unauthorizedHandler' => [
'className' => 'Authorization.CakeRedirect',
'url' => '/',
'queryParam' => 'redirectUrl',
]
]))
->add(new RequestAuthorizationMiddleware());
return $middlewareQueue;
}
/**
* @return void
*/
protected function bootstrapCli(): void
{
$this->addPlugin(\Migrations\Plugin::class);
$this->addOptionalPlugin(\Bake\Plugin::class);
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request Request
* @return \Authentication\AuthenticationServiceInterface
*/
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
// Define where users should be redirected to when they are not authenticated
$service->setConfig([
'unauthenticatedRedirect' => false,
'queryParam' => 'redirect',
]);
$fields = [
'username' => 'username',
'password' => 'password'
];
// Load authenticators
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Cookie', [
'fields' => $fields,
]);
$service->loadAuthenticator('Authentication.Jwt');
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/'
]);
// Load identifiers
$service->loadIdentifier('Authentication.JwtSubject', [
'resolver' => [
'className' => 'Authentication.Orm',
'userModel' => 'Users'
]
]);
$service->loadIdentifier('Authentication.Password', [
'fields' => $fields,
'resolver' => [
'className' => 'Authentication.Orm',
'userModel' => 'Users',
'finder' => 'auth'
],
'passwordHasher' => [
'className' => 'Authentication.Fallback',
'hashers' => [
'Default' => [
'className' => 'Authentication.Default'
],
'Legacy' => [
'className' => 'Authentication.Legacy',
'hashType' => 'sha1'
],
]
]
]);
return $service;
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request Request
* @return \Authorization\AuthorizationServiceInterface
*/
public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface
{
$orm = new OrmResolver();
$mapResolver = new MapResolver();
$policy = new RbacPolicy([
'adapter' => $this->buildRbac()
]);
$mapResolver->map(ServerRequest::class, $policy);
$collection = new ResolverCollection([
$mapResolver,
$orm
]);
return new AuthorizationService($collection, [
'identityDecorator' => function ($auth, $user) {
return $user->setAuthorization($auth);
}
]);
}
/**
*
* @return \CakeDC\Auth\Rbac\Rbac;
*/
protected function buildRbac(): Rbac
{
if ($this->rbacInstance) {
return $this->rbacInstance;
}
return $this->rbacInstance = new Rbac([
'autoload_config' => 'permissions',
'role_field' => 'group',
'default_role' => 'guest',
'permissions' => null, // load from file
'log' => true
]);
}
}
<?php
namespace App\Controller;
class UsersController extends AppController
{
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
$this->Authentication->allowUnauthenticated([
'login', 'remember', 'recover', 'logout'
]);
}
// Code continue
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment