Install the plugin with composer from your CakePHP Project’s ROOT directory (where the composer.json file is located)
php composer.phar require "cakephp/authentication:^1.0"
Load the plugin by adding the following statement in your project’s src/Application.php
:
public function bootstrap()
{
parent::bootstrap();
$this->addPlugin('Authentication');
}
Prior to 3.6.0:
Plugin::load('Authentication');
Add the authentication middleware to the middleware queue. See the CakePHP documentation on how to use middleware if you are not familiar with it.
Example of configuring the authentication middleware using the getAuthenticationService()
hook within Application
:
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
/**
* Returns a service provider instance.
*
* @param \Psr\Http\Message\ServerRequestInterface $request Request
* @param \Psr\Http\Message\ResponseInterface $response Response
* @return \Authentication\AuthenticationServiceInterface
*/
public function getAuthenticationService(ServerRequestInterface $request, ResponseInterface $response)
{
$service = new AuthenticationService();
$service->setConfig([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);
$fields = [
'username' => 'email',
'password' => 'password'
];
// Load identifiers
$service->loadIdentifier('Authentication.Password', compact('fields'));
// Load the authenticators, you want session first
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/users/login'
]);
return $service;
}
/**
* Setup the middleware queue your application will use.
*
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue.
* @return \Cake\Http\MiddlewareQueue The updated middleware queue.
*/
public function middleware($middlewareQueue)
{
// Various other middlewares for error handling, routing etc. added here.
// Create an authentication middleware object
$authentication = new AuthenticationMiddleware($this);
// Add the middleware to the middleware queue.
// Authentication should be added *after* RoutingMiddleware.
// So that subdirectory information and routes are loaded.
$middlewareQueue->add($authentication);
return $middlewareQueue;
}
}
If one of the configured authenticators was able to validate the credentials, the middleware will add the authentication service to the request object as an attribute.
Next, in your AppController
load the Authentication Component:
// in src/Controller/AppController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('Authentication.Authentication');
}
By default the component will require an authenticated user for all actions.
You can disable this behavior in specific controllers using
allowUnauthenticated()
:
// in a controller beforeFilter or initialize
// Make view and index not require a logged in user.
$this->Authentication->allowUnauthenticated(['view', 'index']);
Once you have the middleware applied to your application you’ll need a way for
users to login. A simplistic login action in a UsersController
would look
like:
public function login()
{
$result = $this->Authentication->getResult();
// If the user is logged in send them away.
if ($result->isValid()) {
$target = $this->Authentication->getLoginRedirect() ?? '/home';
return $this->redirect($target);
}
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->error('Invalid username or password');
}
}
Make sure that you whitelist the login
action in your controller’s
beforeFilter()
callback as mentioned in the previous section, so that
unauthenticated users are able to access it:
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
$this->Authentication->allowUnauthenticated(['login']);
}
and then add a simple logout action:
public function logout()
{
$this->Authentication->logout();
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
In order to login your users will need to have hashed passwords. You can automatically hash passwords when users update their password using an entity setter method:
// in src/Model/Entity/User.php
use Authentication\PasswordHasher\DefaultPasswordHasher;
class User extends Entity
{
// ... other methods
// Automatically hash passwords when they are changed.
protected function _setPassword(string $password)
{
$hasher = new DefaultPasswordHasher();
return $hasher->hash($password);
}
}