Jens Segers on

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'] = 'K5c4dr?yu@-6pEs6ek7na#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

Webmentions

Tweet about this blog post and you will appear below!