david winter

Authentication with CodeIgniter 2.0

I’ve started using CodeIgniter again recently, and have noticed that my how-to on implementing basic authentication could do with an upgrade for version 2.0.

The process is identical. We subclass the base CI_Controller class. This simply checks whether a logged in session is present. If not, it redirects the user to a sessions controller that can handle the logging in of a user. Once the user is logged in, the controller acts as normal.

So, first up, lets create our basic subclass:

<?php

class MY_Controller extends CI_Controller
{
    function __construct()
    {
        parent::__construct();

        $this->load->library('session');

        if (!$this->session->userdata('loggedin'))
        {
            redirect('sessions/login');
        }
    }
}

Now, this needs to be saved to application/core. This is important. You can’t add it to application/library like with the previous how-to. There have been some changes to CI that require the change. This new class is also auto-loaded automatically.

Now, the sessions controller needs to extend CI_Controller. Users don’t need to be authenticated to access this controller.

<?php

class Sessions extends CI_Controller
{
    function __construct()
    {
        parent::__construct();

        $this->load->library('session');
    }

    function login()
    {
        $this->load->view('header');
        $this->load->view('login');
        $this->load->view('footer');
    }

    function authenticate()
    {
        $this->load->model('user', '', true);

        $user = $this->input->post('user');

        if ($this->user->authenticate($user['email'], $user['password']))
        {
            $this->session->set_userdata('loggedin', true);
        }

        redirect('/');
    }

    function logout()
    {
        $this->session->unset_userdata('loggedin');

        redirect('/');
    }
}

Your login view will look something like this:

<h2>Login</h2>
<?php echo form_open('sessions/authenticate'); ?>
    <dl>
        <dt><?php echo form_label('Email', 'user_email'); ?></dt>
        <dd><?php echo form_input(array(
            'name' => 'user[email]',
            'id' => 'user_email'
        )); ?></dd>

        <dt><?php echo form_label('Password', 'user_password'); ?></dt>
        <dd><?php echo form_password(array(
            'name' => 'user[password]',
            'id' => 'user_password'
        )); ?></dd>
    </dl>
    <ul>
        <li><?php echo form_submit('submit', 'Login'); ?></li>
        <li><a href="<?php echo site_url('/'); ?>">Cancel</a></li>
    </ul>
<?php echo form_close(); ?>

Here’s a basic user model you could use. It includes hashing with extra salt security:

<?php

class User extends CI_Model
{
    public function authenticate($email, $password)
    {
        // get salt

        $salt = $this->db->select('salt')->get_where('users', array('email' => $email))->row()->salt;

        if ($salt)
        {
            // hash password with salt and find user

            $hash = sha1($salt.sha1($salt.$password));

            $user = $this->db->select('id')->get_where('users', array(
                'email' => $email,
                'hash' => $hash
            ))->row();

            return $user;
        }

        return false;
    }
}

Now all that’s left is to change the parent classes of the controllers that we want protected from CI_Controller to MY_Controller.

<?php

class Admin extends MY_Controller
{
    ...

Authentication is now in place.

2011-01-29

Questions? Comments? Your 2¢'s? → @davidwinter