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/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

Odoo: Download Binary File in v10

To download any binary file in Odoo10 following is the link: http://127.0.0.1:8069/web/content?model=<module_name>&field=<field_name>&filename_field=<field_filename>&id=<object_id> module_name    - the name of the model with the Binary field field_name         - the name of the Binary field object_id            - id of the record containing particular file. field_filename    - name of a Char field containing file's name (optional). So if you want to call a function on button click and download the file, code is as follow: file_url = "http://127.0.0.1:8069/web/content?model=<module_name>&field=<field_name>&filename_field=<field_filename>&id=<object_id>" return {     'type': 'ir.actions.act_url',     'url': file_url,     'target': 'new' } In Reports or web page, you can use it as: <t t-foreach="files&qu

Odoo/ OpenERP: Customize one2many relational field

I was working on one2many relational field to integration one functionality. Worked on python code and then wrote an xml file for the same. Restarted my server. It showed me the row with headers and 'Add an item' button. When clicked on that it opened a pop-up to provide inputs. It shows all the fields with in sequence of it's own. Q1. I need input fields in other sequence or don't need all fields. A.   In xml you would have wrote code like this : <field name="dirtyhandsphp" widget="one2many_list" colspan="4" nolabel="1"> <tree string="Details">              <field name="field1" />              <field name="field2" />                      ---------------------------------------------              <field name="designation" />         </tree>                                                     </field> Add form section inside and