views:

413

answers:

3

I've just started to play with CodeIgniter 1.7.2 and imendialtly noticed that there is not a built-in library for user authentication.

I don't need anything fancy. It's only to authenticate users in to my back office system. I don't need users and groups, or permissions etc. I just need a script to allow users to login. If a user tries to access a page and they are not logged in they should be denied. But it must be secure and it would be good if it use CI validation library.

Can anyone recommend a library for CI 1.7.2?

I did notice there is a similar post on StackOverflow but it's well out of date and most of the libraries recommended either do not support 1.7.2 or are no longer being maintained.

Most important thing is that is must be secure and simple.

A: 

Well, not very specific to CI is a .htaccess user/password system. Especially if you only have a few users.

It's simple to set up, and is built into every Apache server.

Chacha102
+2  A: 

I tend to roll my own simple authentication library.

Firstly, this is the authentication library. It keeps a user ID token in the session. When authenticating it checks for the existence of this token.

application/libraries/Auth.php

class Auth
{
    var $ci;
    var $user_id;

    function Auth()
    {
        // Get CodeIgniter instance
        $this->ci = get_instance();

        // Fetch token from the session
        $this->user_id = $this->ci->session->userdata('user_id');
    }

    function check()
    {
        return $this->user_id != null;
    }

    function login($user_id)
    {
        // Set token in the session
        $this->ci->session->set_userdata('user_id', $user_id);

        $this->user_id = $user_id;
    }

    function logout()
    {
        // Remove token from the session
        $this->ci->session->unset_userdata('user_id');

        $this->user_id = null;
    }
}

I create my own base controller and authenticate there. For convenience, if authenticated, the base controller loads and stores the current user.

application/libraries/MY_Controller.php

class MY_Controller extends Controller
{
    var $user;

    function MY_Controller()
    {
        parent::Controller();
    }

    function do_auth()
    {
        if ($this->auth->check())
        {
            // Authenticated. Fetch current user
            $this->user = $this->user_model->get_user($this->auth->user_id);
        }
        else
        {
            // Not authenticated. Redirect to login page
            redirect('users/login');
        }
    }
}

Then in any action I can call the authentication function of the base controller.

class Items extends MY_Controller
{
    function Items()
    {
        parent::MY_Controller();
    }

    function create()
    {
        // Do authentication
        $this->do_auth();

        // Continue with handling request
    }
}

If I like I can also secure an entire controller.

class Items extends MY_Controller
{
    function Items()
    {
        parent::MY_Controller();

        // Secure entire controller
        $this->do_auth();
    }
}

I place the login and logout actions in a users controller. In the login action I verify the user's credentials and log in the user.

class Users extends MY_Controller
{
    function Users()
    {
        parent::MY_Controller();
    }

    function login()
    {
        // Verify form input
        $this->load->library('form_validation');
        $this->form_validation->set_rules('username', 'Username', 'required');
        $this->form_validation->set_rules('password', 'Password', 'required');

        if ($this->form_validation->run())
        {
            // Fetch the user based on credentials supplied
            $user = $this->user_model->get_user_by_credentials($this->input->post('username', true), $this->input->post('password', true));

            if ($user != null)
            {
                // Credentials verified. Log the user in.
                $this->auth->login($user->user_id);
                redirect('');
            }
            else
            {
                // Login failed. Show the login page.
                $this->load->view('users/login', array('login_failed' => true));
            }
        }
        else
        {
            // Yet to authenticate. Show the login page.
            $this->load->view('users/login', array('login_failed' => false));
        }
    }

    function logout()
    {
        $this->auth->logout();
        redirect('users/login');
    }
}
Stephen Curran
Why are you extending the controller for things that should be done in the login function or a library?
Tom Schlick
I could have done it that way. But then the authentication library would have needed to redirect to my specific login page. I considered this more the concern of my application controller. I thought the authentication library should just be concerned with checking for the existence of the token.
Stephen Curran
Oh ok, the approach i normally take is to record the page they tried to access, redirect them to login/register, after successful login they are directed back to the original page. But your solution works also... ill keep it in mind :)
Tom Schlick
Yeah - I'd normally do the same :-) I'd pass the URL that they are trying to access to the login page via a query string parameter and then redirect them back once they have logged in. But I was just trying to keep the code here as simple as possible.
Stephen Curran
+2  A: 

DX Auth or Freak Auth are great libraries that will suit almost every need that you may have

http://codeigniter.com/wiki/DX_Auth/

http://codeigniter.com/wiki/FreakAuth/

Tom Schlick
Thanks for this. I've decided to try DX_Auth. It seems very comprehensive and easy to use.
Camsoft