Last active
July 3, 2020 16:11
-
-
Save CauanCabral/27bdb295f7854116e875e4b0c4471289 to your computer and use it in GitHub Desktop.
CakePHP 4.1 Application Sample with Authentication and Authorization middlewares
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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