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.

Ion Auth - Lightweight Auth System based on Redux Auth 2

February 10, 2010 7:00pm

Subscribe [287]
  • #886 / Apr 22, 2011 4:44pm

    pelkin000

    2 posts

    A quick follow up - this problem seems to creep up when I attempt to access a page that is ‘restricted’ without first having gone to a non-restricted page on the same domain first. That is to say, if I open my browser and type in http://www.example.com/restricted - i get the error. But if I type in http://www.example.com/login and THEN (even if i dont log in properly) go to http://www.example.com/restricted it will either let me in or redirect me correctly (depending on if i actually logged in).

    Hopefully that helps.

  • #887 / Apr 22, 2011 6:27pm

    idealws

    14 posts

    First let me say thank you for the addition to CI. It is working well and saved me a lot of time.

    My question is about the last login. I noticed that when I login it updates the last login as the current login which is fine except unless I am missing something, how do I get the actual last login for the current user?

    To explain I think they know they are logging in right this minute and where they are logging in from. I believe the purpose of the last login would be to show the user when they or someone else had logged in before todays login.

    Is there something I missed so I can show the last login before the users login is updated?

    Hopes this makes since,

    Regards,
    Ray

  • #888 / Apr 22, 2011 6:55pm

    idealws

    14 posts

    I didn’t find what I was looking for so here is what I did in case there is someone else looking for the samething:

    Modify the users table to be like so:

    CREATE TABLE `tcs_users` (
      `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
      `group_id` mediumint(8) unsigned NOT NULL,
      `ip_address` char(16) NOT NULL,
      `username` varchar(15) NOT NULL,
      `password` varchar(40) NOT NULL,
      `salt` varchar(40) DEFAULT NULL,
      `email` varchar(100) NOT NULL,
      `activation_code` varchar(40) DEFAULT NULL,
      `forgotten_password_code` varchar(40) DEFAULT NULL,
      `remember_code` varchar(40) DEFAULT NULL,
      `created_on` int(11) unsigned NOT NULL,
      `last_login` int(11) unsigned DEFAULT NULL,
      `last_login_ip` varchar(20) DEFAULT NULL,
      `active` tinyint(1) unsigned DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    Notice the addition of last_login_ip

    I then modified the ion_auth_model.php file located in the models directory (there are two modifications made):

    First change was with the login function lines 560-615:

    /**
         * login
         *
         * @return bool
         * @author Mathew
         **/
        public function login($identity, $password, $remember=FALSE)
        {
            if (empty($identity) || empty($password) || !$this->identity_check($identity))
            {
            return FALSE;
            }
    
            $query = $this->db->select($this->identity_column.', id, password, group_id, last_login, ip_address')
                      ->where($this->identity_column, $identity)
                      ->where('active', 1)
                      ->where($this->ion_auth->_extra_where)
                      ->limit(1)
                      ->get($this->tables['users']);
    
            $result = $query->row();
    
            if ($query->num_rows() == 1)
            {
            $password = $this->hash_password_db($identity, $password);
    
            if ($result->password === $password)
            {
    
                $group_row = $this->db->select('name')->where('id', $result->group_id)->get($this->tables['groups'])->row();
    
                $session_data = array(
                        $this->identity_column => $result->{$this->identity_column},
                        'id'                   => $result->id, //kept for backwards compatibility
                        'user_id'              => $result->id, //everyone likes to overwrite id so we'll use user_id
                        'group_id'             => $result->group_id,
                        'group'                => $group_row->name,
                        'userlastlogin'        => $result->last_login,
                        'userlastloginip'      => $this->session->userdata('ip_address')
                         );
    
                $this->session->set_userdata($session_data);
                    
                $this->update_last_login($result->id, $this->session->userdata('ip_address'));
            
                if ($remember && $this->config->item('remember_users', 'ion_auth'))
                {
                $this->remember_user($result->id);
                }
    
                return TRUE;
            }
            }
    
            return FALSE;
        }

    Next I changed the update_last_login function lines 969-987:

    /**
         * update_last_login
         *
         * @return bool
         * @author Ben Edmunds
         **/
        public function update_last_login($id,$lastloginip)
        {
            $this->load->helper('date');
    
            if (isset($this->ion_auth->_extra_where) && !empty($this->ion_auth->_extra_where))
            {
                $this->db->where($this->ion_auth->_extra_where);
            }
    
            $this->db->update($this->tables['users'], array('last_login' => now(), 'last_login_ip' => $lastloginip), array('id' => $id));
    
            return $this->db->affected_rows() == 1;
        }

    Now the users last login will be available via session data like so:

    echo $this->session->userdata('userlastlogin')
    echo $this->session->userdata('userlastloginip')

    Hope this helps. Might already be in there somewhere but I could not find it. This will allow you to print out the last login for this user not the current login.

    Regards,
    Ray

  • #889 / Apr 23, 2011 4:11am

    austintbiggs

    40 posts

    Will you be updating Ion Auth to fit the new CI_Controller / CI_Model and public / private functions?

    instead of using

    if ( ! class_exists('Controller'))
    {
        class Controller extends CI_Controller {}
    }
    
    class Auth extends Controller {
    
        //redirect if needed, otherwise display the user list
        function index()
        {

    using

    class Auth extends CI_Controller {
    
        //redirect if needed, otherwise display the user list
        public function index()
        {
  • #890 / Apr 23, 2011 2:29pm

    Vanitas

    12 posts

    Hi, for few days I’m playing with different auth libraries.

    @EDIT
    I used active records instead of ion auth functions and now works fine 😉

  • #891 / Apr 24, 2011 9:42pm

    ubuntu7290

    1 posts

    Hi,
    So I am using your library to create a social networking type application.  I want it to keep the user logged in after they create a new profile, but I can’t figure out why it won’t.  After they create the new profile, it redirects them to the login page. I have changed the redirect, but it still doesn’t work.  Can you tell me how I can get it to keep the user logged in after they create the profile?

  • #892 / Apr 25, 2011 9:26am

    vivekh

    4 posts

    Can someone please explain the use of meta table?

  • #893 / Apr 25, 2011 1:34pm

    Madoc

    24 posts

    Hello there,

    I decided to try an implement a maximum failed login system for Ion auth (that I use on my project). Even though I am very new at php and indeed codeigniter, I thought I would share my work hoping this might help some people.

    I am also posting this in the hope at you experts will find ways to improve it and make it more secure and more generic as this only works with MySQL at the moment for query optimisation motivations from my part.

    Anyway, here is my code. Please dont be too harsh !

    /*
     * CREATE TABLE
     * ip_address: ip address of the person that attempted to login
     * datetime: when the login attempt happened
     * identity: email or username depending on ion_auth settings
    */
    DROP TABLE IF EXISTS `auth_failed_login`;
    CREATE TABLE IF NOT EXISTS `auth_failed_login` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `ip_address` varchar(15) NOT NULL,
      `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `identity` varchar(255) NOT NULL,
      PRIMARY KEY (`id`)
    );
    
    /*
     * ion_auth CONFIG FILE
     */
    //add to the tables list
    $config['tables']['failed_login']    = 'auth_failed_login';
    //number of failed login attempts allowed
    $config['max_attempts'] = 5;
    //limit the max_attempts to an amount of time
    //i.e default = 5 attempts allowed within 180 seconds (5 minutes)
    $config['max_within'] = 300;
    //number of seconds after the last failed attempt the user
    //will not be allowed to login (ban time). default = 600 seconds (10 minutes)
    $config['ban_seconds'] = 600;
    
    /*
     * ion_auth_model MODEL FUNCTIONS
     */
    
    /**
     * add_failed_login
     *
     * create a new failed login line on the database
     *
     * @return bool
     * @author Madoc
     **/
    public function add_failed_login($identity, $ipaddress)
    {
        if (!$identity || !$ipaddress) : return false; endif;
    
        $this->db->set('ip_address', $ipaddress);
        $this->db->set('identity', $identity);
        $this->db->set('datetime', 'now()', false);
    
        return $this->db->insert($this->tables['failed_login']);
    }
    
    /**
     * get_count_failed_logins
     *
     * get the number of failed login attempts for a given $identity
     * within the period $datefrom to ($datefrom - $period_seconds)
     *
     * @return int
     * @author Madoc
     **/
    public function get_count_failed_logins($identity, $datefrom, $period_seconds)
    {
    
        if (!$identity) : return 0; endif;
        if (!$datefrom) : return 0; endif;
        if (!$period_seconds) : return 0; endif;
        if (!is_numeric($period_seconds)) : return 0; endif;
    
        $sqlquery = "select count(*) as nbattempts from " . $this->tables['failed_login'];
        $sqlquery .= " where identity = '".$identity."'";
        $sqlquery .= " and datetime between DATE_ADD('".$datefrom."', INTERVAL -".$period_seconds." SECOND) and now()";
    
        $result = $this->db->query($sqlquery);
    
        if ($result)
        {
            $row = $result->row_array();
            return (int)$row['nbattempts'];
        }
        else
        {
            return 0;
        }
    
    }
    
    /*
     * get_last_attempt
     *
     * returns the timestamp of the last failed attempt for $identity
     * and time difference in seconds between the last failed login attempt
     * for $identity and NOW()
     *
     * @author Madoc
     *
     */
    public function get_last_attempt($identity)
    {
        if (!$identity) : return false; endif;
    
        $this->db->select('datetime, TIME_TO_SEC(TIMEDIFF(NOW(), datetime)) as timediff',false);
        $this->db->where('identity', $identity);
        $this->db->order_by('datetime','desc');
        $this->db->limit(1);
    
        $result = $this->db->get($this->tables['failed_login']);
    
        if ($result->num_rows > 0)
        {
            $row = $result->row_array();
            return $row;
        }
        else
        {
            return false;
        }
    }
    
    /*
     * Ion_auth LIBRARY FUNCTIONS
     */
    
    /**
     * is_user_banned
     *
     * returns true if the identity is banned, false otherwise.
     * identity banned = the identity was used more than the
     * maximum number of attempts within the maximum allowed failed time
     * and for which the last failed login attempt timestamp is
     * within the banned period (or the max_within if bigger)
     *
     * @return bool
     * @author Madoc
     **/
    public function is_user_banned($identity)
    {
        if (!$identity) : return false; endif;
    
        $max_attempts = $this->ci->config->item('max_attempts', 'ion_auth');
        $ban_seconds = $this->ci->config->item('ban_seconds', 'ion_auth');
        $max_within = $this->ci->config->item('max_within', 'ion_auth');
    
        //get the last attempt
        $last_attempt_array = $this->ci->ion_auth_model->get_last_attempt($identity);
        if ($last_attempt_array)
        {
            //time difference between now and the last failed attempt
            $timediff = $last_attempt_array['timediff'];
            //datetime of the last failed attempt
            $last_attempt = $last_attempt_array['datetime'];
            //number of failed attempts between the last failed attempt and the max_within
            $count_failed_logins = $this->ci->ion_auth_model->get_count_failed_logins($identity, $last_attempt, $max_within);
    
            //not banned if the maximum number of attempts is not reached
            if ($count_failed_logins >= $max_attempts)
            {
                //at this point, end of ban = end of ban period
                //or end of max_minthin if it is longer
    
                if ($max_within > $ban_seconds) : $max_time = $max_within; else: $max_time = $ban_seconds; endif;
    
                if ($timediff < $max_time)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            //no time difference means no record for this attempt
            return false;
        }
    }

    The is_user_banned function is used on my controller prior the login and if the login fails. The table is populated with a new line if the login fails and the user is not banned yet.

    PS: Should I post that somewhere else ?

  • #894 / Apr 25, 2011 8:42pm

    Ben Edmunds

    812 posts

    austintbiggs,

    That is done for CI 1.x compatibility.  That will work with CI1 or CI2 so there is no need to change it.

  • #895 / Apr 25, 2011 8:42pm

    Ben Edmunds

    812 posts

    vivekh,

    The meta table holds the non-essential user data, aka profile data.

  • #896 / Apr 25, 2011 8:43pm

    Ben Edmunds

    812 posts

    ubuntu7290,

    You’ll need to post your controller code.

  • #897 / Apr 25, 2011 8:57pm

    Ben Edmunds

    812 posts

    Madoc,

    From a quick glance that code looks pretty good.  Here’s a little constructive criticism:

    I really hate when people use php alt syntax outside of a view, I would recommend changing that for uniformity. 

    Also, some of your logic could be simplified, for example the is_user_banned() method should return FALSE by default and then the only additional return statements you need are when you’re returning TRUE.

    If I was using this I would integrate it into the login() method as well so your controller code doesn’t change.

  • #898 / Apr 25, 2011 10:41pm

    ReyPM

    86 posts

    Hi:
    I’m rebuilding a entire system which have a DB with a lot of data (I’m talking a DB with 900 MB or even more). This DB has a table called “usuario” where user credentials are stored. Can I use or extend Ion to work with this scene?

    Cheers and thanks in advance

  • #899 / Apr 26, 2011 1:00pm

    Ben Edmunds

    812 posts

    ReyPM,

    Your best bet is probably to add all the additional fields you need to the meta table and then write a script to port the data over.  The only real issue will be the password encryption.

  • #900 / Apr 26, 2011 1:07pm

    ReyPM

    86 posts

    Well I use my own encryption method for all the data because it’s very sensitive so maybe I need to change something in Ion for get it working. Where I can find any doc for developers or something like that to start studying?

    Cheers and thanks

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

ExpressionEngine News!

#eecms, #events, #releases