</> Code The Pixel

CakePHP 4 Log User Authentication Using Component

Asyraf Wahi Anuar - March 10, 2022

Estimated reading time: 3 minutes, 51 seconds

This tutorial will discuss how to create a user activities log using the CakePHP component. The basic activities that will be logged are the authentication method which includes the login and logout details. Technically, the logs will capture the authenticated user_id; action (login/logout); user agent; operating system; IP address; host; referrer; status and when the action is taken. According to CakePHP Book (2022), components are packages of logic that are shared between controllers. CakePHP comes with a fantastic set of core components you can use to aid in various common tasks. You can also create your own components. If you find yourself wanting to copy and paste things between controllers, you should consider creating your own component to contain the functionality. Creating components keeps controller code clean and allows you to reuse code between different controllers. 

The Database Table
Create the database using the following schema:

/*
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| user_id   | int(11)      | YES  |     | NULL    |                |
| action    | varchar(255) | YES  |     | NULL    |                |
| useragent | varchar(256) | YES  |     | NULL    |                |
| os        | varchar(255) | YES  |     | NULL    |                |
| ip        | varchar(50)  | YES  |     | NULL    |                |
| host      | varchar(255) | YES  |     | NULL    |                |
| referrer  | varchar(255) | NO   |     | NULL    |                |
| status    | int(1)       | YES  |     | 1       |                |
| created   | datetime     | YES  |     | NULL    |                |
| modified  | datetime     | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
*/
CREATE TABLE `user_logs` (
  `id` int(11) NOT NULL,
  `user_id` int(11) DEFAULT NULL,
  `action` varchar(255) DEFAULT NULL,
  `useragent` varchar(256) DEFAULT NULL,
  `os` varchar(255) DEFAULT NULL,
  `ip` varchar(50) DEFAULT NULL,
  `host` varchar(255) DEFAULT NULL,
  `referrer` varchar(255) NOT NULL,
  `status` int(1) DEFAULT 1,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `user_logs`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `user_logs`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;


The UserLogs Components
You can bake the UserLogsComponent using the following command and it will generate the UserLogsComponent.php

bin/cake bake component user_logs

or simply create the components file at ...\src\Controller\Component\UserLogsComponent.php and paste the following code. The public function userLoginActivity is used to capture the action details for login and userLogoutActivity will capture logout action details. For this example, I use CakePHP Authentication Plugin.

<?php
declare(strict_types=1);

namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\ORM\Locator\LocatorAwareTrait;
use Cake\Http\ServerRequest;

class UserLogsComponent extends Component
{ 
    use LocatorAwareTrait;
    
    protected $_defaultConfig = [];

    public function userLoginActivity($user_id)
    {
        $request = new ServerRequest;
        $userLogTable = $this->getTableLocator()->get('UserLogs');
        $userlog = $userLogTable->newEmptyEntity();
        $userlog->user_id = $user_id;
        $userlog->ip = $request->clientIp();
        $userlog->action = 'Login';
        $userlog->useragent = $_SERVER['HTTP_USER_AGENT'];
        $userlog->os = php_uname('v');
        $userlog->host = gethostname();
        $userLogTable->save($userlog);
    }
    
    public function userLogoutActivity($user_id)
    {
        $request = new ServerRequest;
        $userLogTable = $this->getTableLocator()->get('UserLogs');
        $userlog = $userLogTable->newEmptyEntity();
        $userlog->user_id = $user_id;
        $userlog->ip = $request->clientIp();
        $userlog->action = 'Logout';
        $userlog->useragent = $_SERVER['HTTP_USER_AGENT'];
        $userlog->os = php_uname('v');
        $userlog->host = gethostname();
        $userlog->referrer = $_SERVER['HTTP_REFERER'];
        $userLogTable->save($userlog);
    }
}


Load UserLogs Component
In your User Controller, load the UserLogs component in the public function initialize as shown below:

public function initialize(): void
{
    parent::initialize();
    
    $this->loadComponent('UserLogs');
}


Add the following code to your login/logout method. Depending on your auth method, call the user_id to capture the authenticated user.

//login
$this->UserLogs->userLoginActivity($this->Authentication->getIdentity('id')->getIdentifier('id'));
//logout
$this->UserLogs->userLogoutActivity($this->Authentication->getIdentity('id')->getIdentifier('id'));


The following codes are examples of the UserLogs component applies in the login and logout method.

public function login()
{
    $this->request->allowMethod(['get', 'post']);
    $result = $this->Authentication->getResult();
    if ($result->isValid()) {
        $this->UserLogs->userLoginActivity($this->Authentication->getIdentity('id')->getIdentifier('id'));
        $redirect = $this->request->getQuery('redirect', ['prefix' => 'Admin', 'controller' => 'Dashboards', 'action' => 'index']);
        return $this->redirect($redirect);
    }
    if ($this->request->is('post') && !$result->isValid()) {
        $this->Flash->error(__('Invalid username or password'));
    }
}

public function logout()
{
    $result = $this->Authentication->getResult();
    if ($result->isValid()) {
        $this->UserLogs->userLogoutActivity($this->Authentication->getIdentity('id')->getIdentifier('id'));
        $this->Authentication->logout();
        return $this->redirect(['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'login']);
    }
}


As the codes are applied in your project, they will capture the details of the login and logout method. You can create the view for the user_logs table to browse the data. That's all. Happy coding.


Cite this article (APA 6th Edition)

Popular
CakePHP 4 Print PDF Using CakePDF
May, 17 2020
CakePHP 4 Authentication Using Auth...
May, 14 2020
CakePHP 4 Sending Email
February, 01 2022
CakePHP 4 jQuery Date Time Picker
October, 01 2018
CakePHP 4 Export To CSV
May, 29 2020
CakePHP 4 Authentication Using...
May, 11 2020
CakePHP 4 Find, Sort & Count
June, 02 2020
Share
Sharing Link
Click the icon to share