Jens Segers on Aug 11 2011

CodeIgniter secure authentication library

A few months ago I released a simple cookie-only authentication library for simple websites. Security is getting more important these days so I decided to release my secure library that I use for more serious/bigger websites that need this security.

Installation

Download the library and example from github, and place the files in their respective folders. The repository contains a database.sql file with the required database structure.

Configuration

Edit the auth.php configuration file to fit your specific environment:

/*
| -------------------------------------
| Authentication configuration
| -------------------------------------
| The basic settings for the auth library.
|
| 'cookie_name'       = the name you want for the cookie
| 'cookie_expire'  = the number of SECONDS you want the cookie to last
| 'cookie_encrypt' = encrypt cookie with encryption_key
| 'hash_algorithm' = the hashing algorithm used for autologin keys
| 'identification' = the database field that is used to identify the user
*/

$config['cookie_name']    = 'autologin';
$config['cookie_expire']  = 31536000;
$config['cookie_encrypt'] = TRUE;
$config['hash_algorithm'] = 'sha256';
$config['identification'] = 'username';

/*
| -------------------------------------
| Model options
| -------------------------------------
| If you use a custom model and or a different database structure,
| adjust these values so that the library uses the correct methods.
|
| 'primary_key'    = the primary key of your users database table
| 'user_model'    = the name of your user model
| 'autologin_model' = the name of the autologin model
*/

$config['primary_key'] = 'id';
$config['user_model']  = 'user_model';
$config['autologin_model'] = 'autologin_model';

If you prefer, you can autoload the library by adjusting your autoload.php file and add 'auth' to the $autoload['libraries'] array.

Usage

A simple implementation example of this library is included in the github repository, so be sure to check out the example. These are the available methods:

  • login($identification, $password, $remember) - authenticate a user using their credentials and choose whether or not to create an autologin cookie
  • logout() - logout function, destroys session and autologin keys
  • loggedin() - returns whether the user is logged in or not, TRUE/FALSE
  • userid() - returns the current user's id
  • username() - returns the current user's username
  • email() - returns the current user's email
  • hash($password) - returns the hashed password to store in the database (to use in your model)

The email and username methods are an example of the dynamic user access. If you database table would have an extra column called 'nickname' you will have access to that information by nickname().

If the login would fail, an error message is stored in $this->auth->error. This is en example of how your controller could look like:

if($this->auth->loggedin()) {
    /* user is already logged in */
    redirect("admin");
}

if($this->auth->login($this->input->post("username"), $this->input->post("password"), TRUE)) {
    /* credentials are correct */
    redirect("admin");
}
else {
    /* login failed, show form with errors */
    $error = $this->auth->error;

    switch($error) {
        case "not_found":
            $error = "Account not found";
            break;
        case "not_activated":
            $error = "Account not activated";
            break;
        case "wrong_password":
            $error = "Wrong password";
            break;
        default:
            $error = "Login error";
    }

    $this->load->view("login", array("error"=>$error));
}

Model communication

This library does not serve as a model for your user database. This library is developed in such a way that it can be coupled to whatever user model you are using. Many other authentication act as a model (or a facade). This is not what I wanted for this library, because libraries should be exchangeable between projects.

The library only uses the get($id) method of the included example model to retrieve a specific user's information. Feel free to change the model name and methods to adjust the library to your environment.

Security: password hashing

The first keypoint of this library is generating secure password hashes. There are many ways to store your user's passwords in your database but unfortunately many ways to crack them. I opted to use the phpass framework because it is written by security experts, has been proven to be secure and is used by popular CMS's and forums like WordPress, phpBB, Drupal, etc.

Security: autologin cookies

Cookies are not safe, they are vulnerable for cookie-theft and cross-site scripting attacks. Users are able to view and even edit the cookie's content, so accept that cookies are not safe. Persistent login cookies are on their own a sufficient authentication method to access a website, they are the equivalent of both a valid username and password.

This is how I made these cookies (more) secure:

They consist of a user's id and a random generated key. This key is not generated by using the user's credentials but a completely random generated key. We need to keep these keys in our database so that each user has a list of available autologin keys to verify the cookie. Users may be mapped to several keys, so that they can use autologin from different locations. Every time an autologin key is used, the key is invalidated and a new key is generated. When a user is authorized CodeIgniter's session management takes over. When a user logs out, their current autologin key is invalidated. Imagine yourself unlocking a door, destroying the key, replacing the lock and taking a brand new key with your for the next time you need to open that door. This is how these autologin cookies work.

Security: CodeIgniter

CodeIgniter has some helpfull options to improve your website's performance. First you should provide an encryption key and enable cookie encryption. By doing this, the cookie's content will be obscured.

$config['encryption_key'] = '[email protected]#r-yupu+aXE';
$config['sess_encrypt_cookie'] = TRUE;

A second option is enabling global XSS filtering. By enabling this all POST and COOKIE data will be filtered from embed malicious javascript or other types of code that attempt to hijack cookies or do malicious things.

$config['global_xss_filtering'] = TRUE;

A final security measure is Cross Site Request Forgery, this was described in one of my previous post.

$config['csrf_protection'] = TRUE;

http://www.openwall.com/phpass
http://en.wikipedia.org/wiki/Bcrypt
http://codeigniter.com/user_guide/libraries/security.html


Comments

Jens Segers 5 years ago

@desta, this authentication library should work on any of your existing models. If you want multiple roles, you need to check this yourself. I wrote this library with the idea that it can be used with any model you want.


desta 5 years ago

thx, but it's only 2 users?, admin and general user, how if, we set to 3 or more user with different role, sory, i just ask it, in other side, we find huge library with more user/role, just ask my stupid thinker. thx again.


Deroccha 5 years ago

thanks a lot! between I found the way as well. Congrats for this library it has a good potential


Jens Segers 5 years ago

I have made a demo controller that shows you how to add your first user: https://github.com/segersjens/...Remember to NEVER save your user's original passwords to your database!


Deroccha 5 years ago

Okay seems to have sense. I added manually through phpmyadmin. Can you give me an example how to handle this.


Jens Segers 5 years ago

How did you add a user to your database? You should use the user_model to add a first user to you database, otherwise the password will not be hashed.


Deroccha 5 years ago

hello again and sorry to bother you. I filled up the sql table and I was giving a try, but somehow the password won't get through(Wrong password). If I make an echo than than the values are seems to be ok. What should I check to debug it?


Deroccha 5 years ago

Thanks!


Jens Segers 5 years ago

Deroccha, thank you for your reply. The model should be renamed to user_model, I have pushed a new version to github that fixes this problem: https://github.com/segersjens/...


Deroccha 5 years ago

hi!I'm trying to use your library. so when I point to the controller http://localhost/proj/admin than I'm getting an error that the user_model was not found. I'm trying to debug it but till now without any success. To model is on the right place.