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]
  • #31 / Nov 22, 2007 12:58am

    Michael Wales

    2070 posts

    Are you using CodeIgniter’s default session library?

    The try_login() function will verify the user’s authentication information and create the user_id session variable. From that point on you can use the try_session_login() function to determine whether the user is logged in or not.

    ErkanaAuth never attempts a straight Cookie approach - it’s always via session.

  • #32 / Nov 22, 2007 6:49pm

    cosmik_roger

    3 posts

    thanks u for the reply.
    Yes I use CI sessions, but the strange thing is that try_login() register well the data but try_session_login can’t retrieve it, I loaded CI session’clas in my controller, but it didn’t get better. I will have more time at the end of this week to dive into the code, and will post what was my problem.
    Anyway, as I began using only cookies, it worked well, and tour class can be a simple way to store some user preferences without authentication.
    Thank you man!

  • #33 / Nov 23, 2007 6:55pm

    cosmik_roger

    3 posts

    Hi, It’s ok with use of Native Session, I wasn’t aware of this Class, and misunderstood Native session like native CI session, it’s ok now with native php sessions 😉

  • #34 / Nov 24, 2007 11:39am

    DarkGrave

    3 posts

    I don’t know if anyone told you this but you should correctly code this part:

    if ($this->erkanaauth->try_login('username'=>$username, 'password'=>$password)){

    It should be:

    if ($this->erkanaauth->try_login(array('username'=>$username), array('password'=>$password))){

    - Someone has told you this before; However it was never updated.

  • #35 / Nov 24, 2007 12:35pm

    DarkGrave

    3 posts

    Sorry for double post but, I wanted to share this with everyone that uses this auth.
    I have added some minor tweaks to make using it go a bit faster.

    Lets start with Configuration:

    Open up the library file: /libraries/Erkanaauth.php

    Insert: var $config After:
    var $CI;

    var $config = array(
                            'user_tbl' => 'users', 
                            'role_tbl' => 'roles', 
                            'user_rows' => array(
                                                'name'     => 'user_name',
                                                'pass'     => 'user_pass',
                                                'email' => 'user_email',
                                                'role'    => 'user_role'
                                                )
                            );

    Alright, Now this is the configuration file I made. You don’t have to use it if you don’t want to just make the necessary changes in the next code where these were used.

    Explanation of Configuration:

    user_tbl  = The name of your "user" table
    role_tbl  = The name of your "role" table
    user_rows = This is where you clarify the most COMMON user rows.
    user_rows are used in such manner:
        'base name' => 'table column / row name'

    Now anywhere inside of the ErkanaAuth Class [still inside the library file] Place these Functions. They aren’t necessary but they are very useful.

    Create User:

    /**
        * Create a user account By DarkGrave
        * With Roles & Autologin. Good for forms.
        *
        * @access    public
        * @param    public array conditions
        * @param    bool
        * @return    bool
        */
        function createUser($user = array(), $role=1, $auto_login=true) {
            $this->CI =& get_instance(); // For PHP 4 USERS.
            
            // Make sure account info was sent
            if(($user['name'] == '') OR ($user['pass'] == '') OR ($user['email'] == '')) {
                return 1; // 1 = Insufficient Information.
            } else {
                $user_name     = $user['name'];
                $user_pass     = $user['pass'];
                $user_email    = $user['email'];
            }
            
            // Check against user table
            $this->CI->db->where($this->config['user_rows']['name'], $user_name);
            $query = $this->CI->db->getwhere($this->config['user_tbl']);
            
            if ($query->num_rows() > 0) {
                return 2; //Username already exists
            } else {
                $password = md5($user['pass']); //Encrypt password
                
                // Insert account into the database
                $data = array(
                                $this->config['user_rows']['name']     => $user_name,
                                $this->config['user_rows']['pass']     => $user_pass,
                                $this->config['user_rows']['email']    => $user_email,
                                $this->config['user_rows']['role']    => $role
                            );
                $this->CI->db->set($data);
                
                if(!$this->CI->db->insert($this->config['user_tbl'])) {
                    return 3; // Problem inserting data into the database.
                }
                $user_id = $this->CI->db->insert_id();
                
                // Automatically login to created account
                if($auto_login){ 
                    $this->erkanaauth->try_login(
                                                    array($this->config['user_rows']['name']=>$username), 
                                                    array($this->config['user_rows']['pass']=>$password)
                                                ); 
                }
                
                // Creation was successfull.         
                return 4; // Make sure you check for 4 not TRUE.
            }
        }

    Example use (No Reasons):

    $result = $this->erkanaauth->createUser(array('name'=>'DarkGrave','pass'=>'test','email'=>'[email protected]'),1,false);
    if($result == 4){
        echo 'Successfully added user!';
    } else {
        echo 'Failed to add user!';
    }
  • #36 / Nov 24, 2007 2:06pm

    Michael Wales

    2070 posts

    @DarkGrave

    Thanks for the changes - I will definitely be implementing those in the newest release. I have also made numerous changes to the library since after that first release. Here’s a rundown:

    The entire library is now 3 methods: try_login(), logout(), and getUser(). try_session_login() is no more, as is getRule() or getField().

    getUser() now returns a user’s record and can be used to determine login status as well as retrieving user information. Right now it doesn’t support roles (so if you use that system, add in a JOIN to the method below) but it will when I actually release this version.

    Here’s the code for getUser():

    function getUser($id = $this->CI->session->userdata('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;
            }
        }

    Here’s an example of how I use it:

    function __construct() {
            parent::Controller();
            $this->data->user = $this->auth->getUser();
        }
    
        // This function is available to anyone:
        function index() {
            $this->load->view('index', $this->data);
        }
    
        // This function is only available to logged in users
        function admin() {
            if (!$this->data->user) redirect('');
            $this->load->view('admin', $this->data);
        }

    Adding role information would be really simple with a join in the method (I just don’t have any use for it in my current contract project), but I envision it’s functionality as:

    function admin() {
            if ($this->data->user->role != 'admin') redirect('');
        }

    The main reason I took this route: the old getRole queried the database every time it was run. If you had 3-4 places throughout a single page that would change, dependent on user role, you either had to assign getRole() to a variable or you just queried the database a lot. This way is a bit more elegant I think and when do you not want the information about the logged in user?

  • #37 / Nov 24, 2007 4:32pm

    DarkGrave

    3 posts

    Mind sending me the new one?

    Here is another function, deleteUser:

    /**
        * Delete user(s) - Function by DarkGrave
        *
        * @access     public
        * @param    integer or Array of integers.
        * @return    bool
        */
        function deleteUser($user_id) {
            $this->CI =& get_instance(); //Put here for PHP 4 users
            
            if(!is_array($user_id)){
                if(!is_numeric($user_id)){
                    return 1; // Id not numerical.
                }
    
                if($this->CI->db->delete($this->config['user_tbl'], array($this->config['user_rows']['id'] => $user_id))) {
                    return 2; //Database call was successful, user was deleted.
                } else {
                    return 3; // Couldn't find user by that id.
                }
            } else {
                $deleted = array();
                
                foreach($user_id as $id){
                    if(!is_numeric($id)){
                        continue; // Id not numerical.
                    }
    
                    if($this->CI->db->delete($this->config['user_tbl'], array($this->config['user_rows']['id'] => $id))) {
                        $deleted[$id] = $id; //Database call was successful, user was deleted.
                    }
                }
                
                return $deleted;
            }
        }

    You will have to add this to the configuration under “user_rows” to use it:

    'id'    => 'id',

    Example usage:

    // Single Deletion
            $result = $this->erkanaauth->deleteUser(1);
            if($result == 2){
                echo "Deleted User.";
            }
    
            // Array Deletion
            $result = $this->erkanaauth->deleteUser(array(2,3,4));
            foreach($result as $deleted_user_id){
                echo "User ".$deleted_user_id." was deleted";
            }

    I see you changed the class from:

    Erkanaauth to auth

    I had to change mine also. It was very long.

  • #38 / Nov 26, 2007 2:20pm

    tomcode

    654 posts

    Hi everybody,

    I’ve been pleased to see Michael’s approach, minimalistic and straight forward.

    I’ve done my own implementation, see My Erkana implementation.

    I will continue to build my solution, but I’d prefer to stick to something common.

    I’ve done it to my likes:
      1. The library is now a model (next version of CI will allow autoload of models)
      2. I rearranged the if clauses inside the methodes
      3. I do not use the helper
      4. The returns of try_login() and getUser() are now the same
      5. Took the table / field names out of the methods

    What do You think of it?

    class Erkanaauth extends Model{
    
        var $db_table = 'users';
        var $db_userid = 'id';
    
        function Erkanaauth()
        {
        
            parent::Model();
            log_message('debug',
                'Authorization class initialized (model Erkanaauth).');
        }
    
        function try_login($condition = array())
        {
            $query = $this->db->getwhere($this->db_table, $condition, 1, 0);
            
            if ($query->num_rows != 1) return FALSE;
            
            $row = $query->row();
            $this->session->set_userdata(array('user_id'=>$row->id));
            
            return $row;
        }
    
        function getUser($id = FALSE)
        {
            if ($id == FALSE) $id = $this->session->userdata('user_id');
            
            if ($id == FALSE) return FALSE;
            
            $condition = array(($this->db_table .'.' .$this->db_userid) =>$id);
            
            $query = $this->db->getwhere($this->db_table, $condition, 1, 0);
            
            $row = ($query->num_rows() == 1) ? $query->row() : FALSE;
            
            return $row;
            }
        
        function logout()
        {
            $this->session->set_userdata(array('user_id'=>FALSE));
        }
  • #39 / Nov 26, 2007 2:40pm

    Michael Wales

    2070 posts

    This looks really good - I’m really excited about all the different directions people have taken Erkana. It was ever my intention to make this a library I maintained and made releases of, I view it as more of an ideology.

    I may have to write a post soon on my blog, outlining/linking to everyone’s ErkanaAuth implementations. :D

  • #40 / Nov 26, 2007 2:58pm

    tomcode

    654 posts

    Dos not everything I do express my opinion ? Anyhow, I want to have lean, modular classes, easily to maintain. I’d like to share them with others, since this helps stabilize the code.

  • #41 / Dec 03, 2007 3:25pm

    stevefink

    136 posts

    Hi Michael,

    Great work! I’m actually using this for a new project. I’m no where near as proficient as you are, so maybe I’m overlooking something here.

    Do you think it might be okay to incorporate a ‘configuration’ section to your library to allow users to set their own table name? ‘users’ is a bit generic, and in an application such as mine it won’t fly. I’m going to have to modify your code where the table is hardcoded everywhere.

    Let me know what you think!

    Cheers bud, awesome coding!

    - sf

  • #42 / Dec 03, 2007 3:41pm

    Michael Wales

    2070 posts

    Yeah, adding in a config section near the top of the library would be optimal. When I originally released ErkanaAuth I never expected it to get the attention it has received thus far - it’s really overwhelming. Unfortunately, I just haven’t had the time recently to incorporate a lot of the awesome changes this community has made to it - plus, the next version will undoubtedly break any application using the current version.

    Feel free to make the changes you feel are necessary and post them for everyone to see. ErkanaAuth has grown into much more than a library but more of an experiment in minimalism vs. functionality - it’s interesting to see everyone’s contributions and the various ways in which we tackle similar issues.

  • #43 / Dec 03, 2007 3:49pm

    stevefink

    136 posts

    Thanks Michael. 😊

    Maybe I can ask you for any suggestions here, and then I’ll try to write up something and send it to you. Feel free to use it (as far as a configuration option.)

    I’m currently having issues with headers using the library. I popped this code into my controller which gets loaded should the user successfully login per the following:

    $this->load->library('Erkanaauth');
            if (!$this->erkanaauth->try_session_login()) {
                redirect('/login');
              }

    I’m receiving a consistent error message:

    ERROR - 2007-12-03 14:43:34—> Severity: Warning —> Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/iphone_pk/system/application/models/dbmodel.php:113) /Applications/MAMP/htdocs/iphone_pk/system/helpers/url_helper.php 455

    Trying to debug it, but not having much luck. Totally would appreciate your help.

    Thanks man. 😊

    - sf

  • #44 / Dec 03, 2007 3:55pm

    Michael Wales

    2070 posts

    Make sure there is no whitespace at the end of Erkanaauth.php (I don’t think there is) - check other custom libraries you are loading as well.

  • #45 / Dec 03, 2007 4:01pm

    stevefink

    136 posts

    Yeah, I can’t for the life of me find a whitespace at the end of any of my controllers/models/views.

    No matter what I do with redirect() I’m getting signaled that headers have already been sent to the browser and it’s screwing up the whole application.

    Fun times!

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

ExpressionEngine News!

#eecms, #events, #releases