Skip to main content

CakePHP Auth Component Implementation


First time I was using Auth component of CakePHP and it took me around 2 complete days to fully understand Auth component and implement it. Documenation is also bit confusing on http://book.cakephp.org/1.3/. I am writing this post for my future reference as well as for those who are having doubts with Auth component. Let's start

1) Very first step is to include Auth component in components array of AppController. As you know for controllers we do most of the common stuff in AppController.

app_controller.php
 
var $components = array('Auth');

2) If you wanna customize Auth component messages and variables use beforeFilter() method for that, as :
     
app_controller.php

function beforeFilter() {
               
                 //it would load User model dynamically. Discussed in detail in step 4
                 $this->Auth->authenticate = ClassRegistry::init('User');
                               
                 //Following is the code to change default variables for username and password
                 //default array is 
                 //var $fields = array('username' => 'username', 'password' => 'password');
                 $this->Auth->fields = array(
                            'username' => 'username',
                            'password' => 'cslab_user_password'
                  );
                  //You can change the default login from /users/login to be any action of your choice.
                  //$this->Auth->loginAction    = array('admin' => false, 'controller' => 'users', 'action' => 'login');
                  //The AuthComponent remembers what controller/action pair you were trying to get to before you were asked to authenticate yourself by storing this value in the Session, under the Auth.redirect key. However, if this session value is not set (if you're coming to the login page from an external link, for example), then the user will be redirected to the URL specified in loginRedirect.
                  $this->Auth->loginRedirect  = array('admin' => false, 'controller' => 'assigned_devices', 'action' => 'index');
                  //You can also specify where you want the user to go after they are logged out, with the default being the login action.
                  $this->Auth->logoutRedirect = array('admin' => false, 'controller' => 'users', 'action' => 'login');
                 //Change the default error message displayed when someone does not successfully log in.                       
                 $this->Auth->loginError     = 'Username/Password Mismatch.';
                //Change the default error message displayed when someone attempts to access an object or action to which they do not have access.                      
                $this->Auth->authError      = 'Please login to view that page.';
 
                 //I have written these three function to check if admin or normal user is logged in and to get username  of the logged in member
                  $this->set('admin',$this->_isAdmin());
                  $this->set('loggedIn',$this->_loggedIn());
                  $this->set('username',$this->_usersUsername());
}

//Checks if user loggedin is an admin
function _isAdmin(){
           $admin = false;
           if($this->Auth->user('role') == ADMIN_ROLE) {
                     $admin = true;
           }
           return $admin;
}
//Checks if user is logged in        
function _loggedIn(){
            $logged_in = false;
            if($this->Auth->user()) {
                         $logged_in = true;
            }
            return $logged_in;
}

//finds username of the loggedin user
function _usersUsername(){
             $users_username = null;
             if($this->Auth->user()){
                       $users_username = $this->Auth->User('username');
             }
             return $users_username;
}

3) Go to your Users controller and write a login() function. 

users_controller.php 
 
function login(){
              //No need to write anything inside function because Auth component handles everything.
}

If you don't wanna customize anything leave it blank otherwise write your code inside. For example  I wanna implement validations on username and password so here is my code : 

function login(){
                  if($this->data){
                             $this->User->set($this->data);
                             if($this->User->validates()){
                                         if ($this->Auth->user()) {
                                                        $this->redirect($this->Auth->redirect());
                                         }
                              }else{
                                          $this->errors = $this->User->validationErrors;
                              }
                    }
                    $this->set('errors',$this->errors);
 }

4) Now write view file :

login.ctp

<?php  echo $session->flash('auth');?> //Display auth messages

<?php  echo $this->Form->create("User"); ?>

<?php echo $this->Form->input("username", array('label' => "Username : ", 'type' => 'text', 'class' => 'tal vat w200p', 'error' => false)); ?><br/>

<?php echo $this->Form->input("pswd", array('label' => "Password : ", 'type' => 'password', 'class' => 'tal vat w200p', 'error' => false)); ?><br/>

<?php echo $this->Html->div("pb10p",$this->Html->link("I forgot my password","/users/forgot",array('class' => 'pl150p')), array('id' => "forgot_password")); ?>

<?php echo $this->Form->end(" Login ",array('class' => 'button')); ?>

Have you noticed i have used "pswd" field name instead of "password" for password field. It's because if we will use "password" field then it would perform automatic hashing even if the field is empty and would skip validation for password as well. I just wanna perform password validation and md5 hashing without salt. So we have to use other name for password field and overwrite hasing. So go to User model and write validation code as well as hashPasswords() function. We also have to set  'authenticate' to the object you're authenticating against (usually this is User, done in step 2) 

user.php
 
var $validate    =   array(
                 'username' => array(
                                'username_should_not_be_empty' => array(
                                                'rule'                      => 'notEmpty',
                                                 'message'            => 'Please Enter Username',
                                                 'last'                       => true
                                 )
                    ),
                    'pswd' => array(
                                    'password_should_not_be_empty' => array(
                                                     'rule'                      => 'notEmpty',
                                                     'message'            => 'Please Enter Password',
                                                      'last'                       => true
                                     )
                     )
);

function hashPasswords($data) {
                if (isset($data['User']['pswd'])) {
                               $data['User']['cslab_user_password'] = md5($data['User']['pswd']);
                                return $data;
                 }
                 return $data;
}


5) To logout from system you have to just write following function :

users_controller.php

function logout(){
               $this->redirect($this->Auth->logout());
}

6) If you wanna another page to get accessed without login, mention it in beforeFilter() function of the controller. For example i also wants to access register and forgot_password functions of users controller  to be accessed publicly then write following code :

users_controller.php

function beforeFilter(){
                parent::beforeFilter();
                $this->Auth->allow('register', 'forgot_password');
 }  

7) You can also your own layout for Authentication error messages like 'authError' and 'loginError' using following line in AppController beforeFilter() function.

message_error.ctp

$this->Auth->flashElement    = "message_error";

this layout file should be saved as ......app\views\elements\message_error.ctp
 
//    Code in /app/views/elements/message_error.ctp
<div class="ui-state-error">
    <?php echo $message; ?>
</div>

8) If you wanna get any information of the loggedin used then you can get it simple as :

$user_email = $this->Auth->user('user_email');

where 'user_email' is users table field.

That's it. If you have any doubt regarding please post your comments below. 


Reference Links : 
 





Thanks!!!!!!!!!! Enjoy Programming :)

Comments

Popular posts from this blog

Odoo: Qweb Templates Cache Issue

Hi Everyone, Today I was working on a hotel booking template in Odoo and changes made in the Qweb template(.xml) were not reflecting on updating module with odoo service restart. Tried few times without any success :(. Finally, I decided to delete the old template from Odoo backend and then update module again and it worked like a charm!! :) Steps to delete template from backend: Settings --> User Interface --> Views --> Search by template name Delete the used template. Although it's a small post, but I'm sure it will meet the purpose and help someone in the future. Thanks!!! Enjoy Programming!! :) Reference Links: =================================== https://www.odoo.com/forum/help-1/question/odoo-cache-and-updating-qweb-templates-84492

Odoo12/13: Add an extra action in the tree view action button

This post will help you to add an action window in Odoo. Odoo13: <act_window id="action_make_bank_payment"              name="Do Bank Payment"              res_model="account.ob.payment"              binding_model="account.move"              view_mode="form"              target="new"              binding_views="list,form"              domain="[('type','=', 'in_invoice')]"              groups="account.group_account_user" /> Odoo12: <act_window id="action_make_bank_payment"              name="Do Bank Payment"              res_model="account.ob.payment"             view_mode="tree,form"              domain="[('type','=', 'in_invoice')]"              groups="account.group_account_user" /> Thanks!!! Enjoy Programming!! :) Reference: https://www.odoo.com/es_

Odoo/OpenERP: one2one relational field example

one2one relational field is deprecated in OpenERP version>5 but you can achieve the same using many2one relational field. You can achieve it in following two ways : 1) using many2one field in both the objects ( http://tutorialopenerp.wordpress.com/2014/04/23/one2one/ ) 2)  using inheritance by deligation You can easily find the first solution with little search over internet so let's start with 2nd solution. Scenario :  I want to create a one2one relation between two objects of openerp hr.employee and hr.employee.medical.details What I should do  i. Add _inherits section in hr_employee class ii. Add field medical_detail_id in hr_employee class class hr_employee(osv.osv):     _name = 'hr.employee'     _inherits = {' hr.employee.medical.details ': "medical_detail_id"}     _inherit = 'hr.employee'         _columns = {              'emp_code':fields.char('Employee Code', si