Using hooks with ion_auth


The best authentication library won't save you from your own logic errors. 
Be sure to consider these common security mistakes:
Web form security - avoiding common mistakes
Like PDO? Check out how to use it with Codeigniter
Codeigniter with PDO

Ion Auth is a solid authentication "suite" (my term) for CodeIgniter, developed by Ben Edmunds with help from Phil Sturgeon & the Codeigniter Community. It is one of the most active, regularly updated authentication libraries out there, which means you can be assured of quick help and bug fixes if you stumble upon a problem.

One of the more useful tools that the library provides is hooks into all of its main functions. Hooks are something that have been around in Codeigniter for quite some time, but have never really seen wide-spread usage. The nice thing about using a hook is that it allows you to make small before or after actions whenever an event occurs without having to extend the entire class.

We're going to use a simple example to show how this works, by using the "post_set_session" to add an additional session variable when we log in. The set_session method is a fairly recent addition, so you may need to update your Ion_auth library if you are already using it.

First, lets understand a little bit about what we are doing. The Ion_auth_model supplies us with two important functions, set_hook() and trigger_events(). A "hook" is almost like an html anchor or code breakpoint - it is a place where we have an entrypoint into the function to insert our own set of code.

Look for a moment at the set_session() function we will use:

public function set_session($user)
{

	$this->trigger_events('pre_set_session');

	$session_data = array(
	    'identity'             => $user->{$this->identity_column},
	    'username'             => $user->username,
	    'email'                => $user->email,
	    'user_id'              => $user->id, //everyone likes to overwrite id so we'll use user_id
	    'old_last_login'       => $user->last_login
	);

	$this->session->set_userdata($session_data);

	$this->trigger_events('post_set_session');

	return TRUE;
}		

You can see the two hooks inside the trigger_events calls - pre_set_session & post_set_session. Those are simply names, with no special meaning other than to be clear where they are called from.

So, we have two hooks already? Well, not exactly. What we have are two places where hooks are checked for - trigger_events() will go look and see if we have set_hook() for either of those. It looks at a private array on the ion_auth_model called $this->_ion_hooks to see if it can find an element with pre_set_session or post_set_session. Since we haven't set any yet, it will simply return and continue.

Let's set a hook then so we can add our session variable. For our example we would like to add the user's twitter name to the session (don't ask me why - obviously something like their company_id would be more practical). So that we can see the code first, let's do it in a static way and see how it works. In Auth.php controller _construct(), at the end of the function, add:

function __construct()
{	
	// ... your existing code 

	// set session post hook
	$event = 'post_set_session';
	$name = 'call_Twitter';

  	$class = $this; 
  	$method = 'twitter';

  	$args = array('codebyjeff');
	
	$this->ion_auth->set_hook($event, $name, $class, $method, $args);	
}

public function twitter( $who) 
{
	$this->session->set_userdata('twitter', $who);
  	return true;
} 	

The first point is, the _construct() is not really the best place to put this, since we would be calling the set_hook() everytime we called the Auth controller. We'll refactor it in a minute - this just makes it easier for us to study, outside of all the other busy code.

Our set_hook() method works like this:

	
  • $event -- this is the event IN THE ION_AUTH_MODEL FUNCTION we would like to call. So for us, every time the set_session() is called, it will fire off our hooked function.
  • $name -- just a label, it has no significance
  • $class & $method-- php's native call_user_func_array() is being used to actually call the function, so we need to provide the class & method we want the hook to trigger. In our case, the class is just $this since we set it up on this same controller, and the method is our twitter() function.
  • $args -- an array of values we will pass into our function, so 'codebyjeff' will get passed into twitter($who) as the value for $who

So, we've set our hook and now whenever the set_session() sets up our session - namely, whenver we log in - it will also set a session variable for "twitter". If you do a var_dump() on $session = $this->session->all_userdata(); in whatever your redirect after login view is, you'll be able to check that it is there.

Fianlly, let's refactor this into something we would really use. Make the following change in the Auth login() function:

...
//if the login is successful
//redirect them back to the home page

//Here you will need to get $user from your logged in user, 
//so you can access all the record fields

//We're going to fake it
$user->twitter = 'codebyjeff';
	
$this->ion_auth->set_hook('post_set_session', 'call_Twitter', $this, 'twitter', array($user->twitter));	

Now the hook is set only when we are logging in, which is really what we are after.

What are the advantages of this technique? It lets us simply add on to pre-written and pre-tested code when we develop rather than adding another class abstraction and potentially more bugs (after all, a great many eyes have seen the code above, but only yours have seen the new code you are writing)

Hope that helped!

Contact me

Do you freelance?

Avoid the stressful ups and downs!
What Mom Forgot to Tell You about Remote and Freelance Work