Authentication in CakePHP4 (Strawberry)
Adding Authentication:
Once you've included the Authentication class, you can get a user's information with the following:
//in any controller
$user = $this->Authentication->getIdentity()
Here's another helpful link: https://book.cakephp.org/4/en/controllers/components/security.html#usage
Checking for user data on login:
$result = $this->Authentication->getResult();
if ($result->isValid()) {
//debug($result->getData()->user_type);exit;
if($result->getData()->user_type <> 'super' && $result->getData()->user_type <> 'admin') {
$this->Flash->error(__('You do not have access to these features.'));
$this->Authentication->logout();
}
if ($result->getData()->locked) {
$this->Authentication->logout();
$this->Flash->error(__('You are not allowed to login, please contact administrator'));
} else {
// redirect to /articles after login success
$redirect = $this->request->getQuery('redirect', [
'controller' => 'Users',
'action' => 'dashboard',
]);
return $this->redirect($redirect);
}
}
// display error if user submitted and authentication failed
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->error(__('Invalid email or password'));
}
Most of this info is from this page in the cookbook: https://book.cakephp.org/4/en/tutorials-and-examples/blog-auth-example/auth.html
Tutorial:
https://codethepixel.com/cakephp/cakephp-4-authentication-authentication-plugin
Adding authentication to the app controller:
composer require cakephp/authentication:^2.0
Bootstrap the method in Application.php
// in src/Application.php in the bootstrap() method.
$this->addPlugin('Authentication');
Add Password Hashing in the User Model:
// src/Model/Entity/User.php
namespace App\\Model\\Entity;
use Cake\\Auth\\DefaultPasswordHasher;
use Cake\\ORM\\Entity;
class User extends Entity
{
// Make all fields mass assignable except for primary key field "id".
protected $_accessible = [
'*' =>true,
'id' =>false];
// ...
protected function _setPassword($password) {
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}
// ...
}
Imports - Application.php
// In src/Application.php add the following imports
use Authentication\\AuthenticationService;
use Authentication\\AuthenticationServiceInterface;
use Authentication\\AuthenticationServiceProviderInterface;
use Authentication\\Middleware\\AuthenticationMiddleware;
use Cake\\Routing\\Router;
use Psr\\Http\\Message\\ServerRequestInterface;
Implement the Authentication Interface in the Application Class - Application.php
// in src/Application.php
class Application extends BaseApplication
implements AuthenticationServiceProviderInterface
{
Add the Middleware to Application.php
// src/Application.php
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue
// ... other middleware added before
->add(new RoutingMiddleware($this))
// add Authentication after RoutingMiddleware
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$all= explode('/',$_SERVER['REQUEST_URI']);
// echo ;exit
$authenticationService = new AuthenticationService([
'unauthenticatedRedirect' => $request->getAttribute('webroot').'admin/users/login',
'queryParam' => 'redirect',
]);
// Load identifiers, ensure we check email and password fields
$authenticationService->loadIdentifier('Authentication.Password', [
'fields' => [
'username' => 'email',
'password' => 'password',
]
]);
// Load the authenticators, you want session first
$authenticationService->loadAuthenticator('Authentication.Session');
// Configure form data check to pick email and password
$authenticationService->loadAuthenticator('Authentication.Form', [
'fields' => [
'username' => 'email',
'password' => 'password',
],
'loginUrl' => Router::url('/admin/users/login'),
]);
return $authenticationService;
}
Load the Component - AppController.php
// src/Controller/AppController.php
publicfunction initialize(): void
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
// Add this line to check authentication result and lock your site
$this->loadComponent('Authentication.Authentication');
publicfunction beforeFilter(\\Cake\\Event\\EventInterface $event)
{
parent::beforeFilter($event);
// Configure the login action to not require authentication, preventing
// the infinite redirect loop issue
$this->Authentication->addUnauthenticatedActions(['login']);
}