ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

ErkanaAuth: A non-invasive user authentication library

October 23, 2007 9:58pm

Subscribe [37]
  • #46 / Dec 03, 2007 4:11pm

    stevefink

    136 posts

    Hate to double post, but I’ll include all of my code… maybe I am indeed doing something seriously stupid.  So here we go. In my login controller I have the following

    Login.php

    function index()
        {
            $this->load->library('Erkanaauth');
            $this->load->library('validation');
            
            /* validation rules for login form */
            $rules['email'] = "trim|required|valid_email|xss_clean|callback__verify_login";
            $rules['pass'] = "trim|required|xss_clean|md5";
            
            $this->validation->set_rules($rules);
            
            if($this->validation->run() == FALSE) {
                $this->load->view('login_view');
            } else {
                redirect('/', 'refresh');    
            }
            
        }

    The function which validates the login within Login.php:

    function _verify_login($email) 
        {
           $this->load->helper('security');
           $password = dohash($this->input->post('pass'), 'md5');
           if($this->erkanaauth->try_login(array('email' => $email, 'password' => $password ))) {
               return TRUE;
           } else {
               $this->validation->set_message('_verify_login', 'Invalid login credentials.');
               return FALSE;
           }
        }

    At this point I have it set to redirect to ‘/’ which should be my default controller set in routes.php… and here I have simple code:

    function index()
        {
            $this->load->library('Erkanaauth');
            if (!$this->erkanaauth->try_session_login()) {
                redirect('/login', 'refresh');
            }
    
            /* We need to fetch some data to populate into the view. 
               Retrieve all available CPT codes. */
            $data['cpt'] = $this->dbmodel->select_cpt_codes();
            
            /* Retrieve all patients that aren't discharged */
            $data['patients'] = $this->dbmodel->select_active_patients();
            
            /* Retrieve current date for CPT population */
            $timestamp = time();
            $data['current_date'] = date("d M Y", $timestamp);
            
            $this->load->view('landing_page_view2', $data);
        }

    Thanks, I know it’s a lot. Would definitely owe ya big time if you catch a stupid mistake I’ve made.

  • #47 / Dec 03, 2007 4:24pm

    tomcode

    654 posts

    What do You have in Your dbmodel.php on line 113 ?

  • #48 / Dec 03, 2007 4:33pm

    stevefink

    136 posts

    I’ll be darned. There -was- white space at the end of my dbmodel.php ?>, not a newline, but just white space on the same line. Shesh that’s hard to catch with the naked eye.  Thank you so much. :-(

    Just curious… is the following legit to redirect to the default controller?

    redirect(”“, ‘refresh’);

    Also for Michael,

    is it safe to assume I can use this code on any controller which requires an authenticated login?

    if (!$this->erkanaauth->try_session_login()) {
                redirect('/login', 'refresh');
            }

    I looked through my cookies and only saw ci_session there, so I wasn’t sure where the other stuff is hiding out on.

    Thanks again guys, you rock.

  • #49 / Dec 03, 2007 6:08pm

    Michael Wales

    2070 posts

    redirect('', 'refresh')

    Yes, that redirect is fine (with or without the second parameter).

    is it safe to assume I can use this code on any controller which requires an authenticated login?

    Yup! Even better, why not create a libraries\MY_Controller.php file with the following code:

    class Auth_Controller extends Controller {
        function auth_controller() {
            parent::Controller();
            if (!$this->erkanaauth->try_session_login()) redirect('/login', 'refresh');
        }
    }

    Then, any controller in which users should be logged in, just extend your Auth_Controller rather than Controller.

    class Products extends Auth_Controller {
    }

    ErkanaAuth uses whichever session library you have installed. So, if you have the native CI session library (with the default setting, naming the cookie ‘ci_session’ - that is all you are going to see).

    One downfall of Erkana is it is only as secure as your cookie settings (since all it does is store the user’s ID). So, be sure to encrypt your cookies and establish a strong encryption key within config.php - otherwise people could just change the user_id in the cookie to any ID they want.

  • #50 / Dec 05, 2007 12:35pm

    tomcode

    654 posts

    Just finished my direct access model, my more universal Ersatz for a forgotten password feature.

    demo installation

    <?php
    
    /**
     * Non-intrusive Direct Access Model
     *
     * This model creates and controls direct access tokens
     * which can be used for features like forgotten password.
     *
     * @package    CodeIgniter
     * @subpackage    Models
     * @category    Authorization
     * @author        Thomas Traub
     * @link        <a href="http://www.tomcode.com/inside/codeigniter/direct_access">http://www.tomcode.com/inside/codeigniter/direct_access</a>
     */
    class Direct_access_model extends Model {
    
        var $db_table = 'direct_access';
        var $hash_field = 'hash';
        
        /** 
         * Creates, stores and returns the direct
         * access token for the passed condition. 
         * Overwrites an exiting old entry.
         * 
         * @param array associative the database query condition
         * @return string the access URL param
         */
        function set_access($condition)
        {
            // create hash
            $data[$this->hash_field] = str_shuffle(uniqid('' .rand(0, 32768)));
    
            // look for an existing entry
            $query = $this->db->getwhere($this->db_table, $condition, 1, 0);
            $row = $query->row();
            
            //  update or insert
            if ($query->num_rows == 0) 
            {
                $condition = array_merge($condition, $data);
                
                $this->db->insert($this->db_table, $condition); 
            }
            else $this->db->update($this->db_table, $data, $condition);
            
            // return only in case of success
            if($this->db->affected_rows() == 1) return array_merge($condition, $data);
        }
        
        /**     
         * Returns the ident data for a passed condition (hash token),
         * and, by default, deletes the found entry.
         * 
         * @param array associative the database query condition
         * @param boolean shall the entry be deleted
         * @return mixed boolean:false or object: the query row
         */
        function get_access($condition, $delete_condition = true)
        {
            $query = $this->db->getwhere($this->db_table, $condition, 1, 0);
            
            if ($query->num_rows != 1) return FALSE;
            
            if($delete_condition) $this->delete_access($condition);
            
            return $query->row();
        }
        
        /**     
         * Deletes an entry based on the passed query condition
         * 
         * @param array associative the database query condition
         */
        function delete_access($condition)
        {
            $this->db->delete($this->db_table, $condition); 
        }
    }
  • #51 / Dec 05, 2007 12:45pm

    xwero

    4145 posts

    great work tomcode a perfect compagnion for the library.

  • #52 / Jan 01, 2008 10:38pm

    Neovive

    57 posts

    Michael: This looks great!  I downloaded the library from your website, but it appears to be the older version.  Is the newly revised “3 method only” version available?

  • #53 / Jan 11, 2008 8:04pm

    benlm

    2 posts

    Does anyone have a version of the erkana library with the changes/fixes listed in this thread?

    The library looks good in terms of size and scope, however one thing I don’t like is the name of the helper functions getField and getRole. I think they should be renamed to be something like erkana_getField/erkana_getRole or userGetField/userGetRole.

  • #54 / Jan 12, 2008 4:14pm

    tomcode

    654 posts

    Does anyone have a version of the erkana library with the changes/fixes listed in this thread?

    There is a version of imzyos on the Wiki.

  • #55 / Jan 13, 2008 11:32am

    BrandonDurham

    74 posts

    How do I go about encrypting my cookies for ErkanaAuth?

  • #56 / Jan 13, 2008 11:39am

    tomcode

    654 posts

    You can encrypt Your cookies by setting the corresponding value in application/config/config.php.

  • #57 / Jan 13, 2008 11:46am

    BrandonDurham

    74 posts

    Ah! Simple, thank you.

  • #58 / Jan 13, 2008 1:05pm

    Michael Wales

    2070 posts

    I’ve had a few requests for the most recent version of ErkanaAuth (the one including the changes listed here in this thread). Well, it doesn’t exist, unfortunately.

    What I do have is the version of ErkanaAuth that I use within all of my development. I’m down to 3 methods and none of the User Management stuff (roles and such). Here, it is - in all it’s glory, with some examples to follow.

    <?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
     
     class Auth {
     
        var $CI;
        
        function __construct() {
            $this->CI =& get_instance();
            log_message('debug', 'Authorization class initialized.');
            
            $this->CI->load->database();
        }
        
    
        function try_login($condition = array()) {
            $this->CI->db->select('id');
            $query = $this->CI->db->getwhere('users', $condition, 1, 0);
            if ($query->num_rows != 1) {
                return FALSE;
            } else {
                $row = $query->row();
                $this->CI->session->set_userdata(array('user_id'=>$row->id));
                return TRUE;
            }
        }
        
        
         function logout() {
            $this->CI->session->set_userdata(array('user_id'=>FALSE));
        }
        
        
        function get_user($id) {
            if ($id) {
                $query = $this->CI->db->getwhere('users', array('users.id'=>$id), 1, 0);
                if ($query->num_rows() == 1) {
                    return $query->row();
                } else {
                    return FALSE;
                }
            } else {
                return FALSE;
            }
        }
     }
     
     ?>


    How I Use It
    logout() is still used the same way - a direct call within a controller, then redirect somewhere.

    I still use try_login() the same way as well - within a callback function

    get_user() is a bit different than what we’ve seen in the past. I usually extend my Controller class, having all of my classes assign the return value to a variable I can us within my view (for echoing out user info, as needed). For any controllers needing Authorization - I make a valid get_user() return value a requirement.

    application/libraries/MY_Controller.php

    <?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
     
    class Public_Controller extends CI_Controller {
        function Public_Controller() {
            parent::Controller();
            $this->data->user = get_user($this->session->userdata('user_id'));
        }
    }
    
    class Admin_Controller extends Public_Controller {
        function Admin_Controller() {
            parent::Controller();
            if ($this->data->user === FALSE) {
                redirect('user/login');
                return;
            }
        }
    }
  • #59 / Jan 13, 2008 1:12pm

    tomcode

    654 posts

    I just wonder why You implement it as library and not as model.

  • #60 / Jan 13, 2008 1:17pm

    Michael Wales

    2070 posts

    Because to me, models define data. This has very little to do with data and a lot to do with business logic.

    A model, for users, would display what fields define a user and the methods used to do things like: create a new user, delete a user, etc.

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases