ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

ErkanaAuth: A non-invasive user authentication library

October 23, 2007 9:58pm

Subscribe [37]
  • #61 / Jan 13, 2008 1:35pm

    tomcode

    654 posts

    I understand that point. I just have this shortcut in my head : CodeIgniter ? data base ? => model.

  • #62 / Jan 13, 2008 1:57pm

    BrandonDurham

    74 posts

    So do you make your above code a library and autoload it?

  • #63 / Jan 13, 2008 3:29pm

    Michael Wales

    2070 posts

    So do you make your above code a library and autoload it?

    Yes.

  • #64 / Jan 15, 2008 11:07am

    flosaurus

    9 posts

    get_user() is a bit different than what we’ve seen in the past. I usually extend my Controller class, having all of my classes assign the return value to a variable I can us within my view (for echoing out user info, as needed). For any controllers needing Authorization - I make a valid get_user() return value a requirement.

    application/libraries/MY_Controller.php

    <?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
     
    class Public_Controller extends CI_Controller {
        function Public_Controller() {
            parent::Controller();
            $this->data->user = get_user($this->session->userdata('user_id'));
        }
    }
    
    class Admin_Controller extends Public_Controller {
        function Admin_Controller() {
            parent::Controller();
            if ($this->data->user === FALSE) {
                redirect('user/login');
                return;
            }
        }
    }

    I’m quite new to CI and would like to know how to use your librarie MY_Controller.php to secure a controler. Could you provide some example ?

    thanks a lot

  • #65 / Jan 15, 2008 2:43pm

    fakeempire

    5 posts

    http://www.michaelwales.com—seems to be down and all download links point to that. Does someone have it mirrored somewhere?

    Thanks

  • #66 / Jan 15, 2008 3:03pm

    Michael Wales

    2070 posts

    fakeempire - it will be back up shortly (Dreamhost had a billing issue which made my account look way overdue).

    You can look at this post and just copy-paste the code into /application/libraries/auth.php and it will work fine.

  • #67 / Jan 15, 2008 3:12pm

    Michael Wales

    2070 posts

    I’m quite new to CI and would like to know how to use your librarie MY_Controller.php to secure a controler. Could you provide some example ?

    Sure thing:

    /application/libraries/MY_Controller.php
    This code will create two classes that extends the Controller class.

    The first class is Public_Controller and allows anyone to access your site. The currently logged in user information is available in your controller as $this->data->user and within your view as $user (if you pass the $this->data object to your view).

    The second class is Admin_Controller and only allows a logged in user to access it. It will redirect to the default controller if a user is not logged in.

    class Public_Controller extends Controller {
      function Public_Controller() {
        parent::Controller();
        $this->data->user = $this->auth->get_user($this->session->userdata('user_id'));
      }
    }
    
    class Admin_Controller extends Controller {
      function Admin_Controller() {
        parent::Controller();
        $this->data->user = $this->auth->get_user($this->session->userdata('user_id'));
        if ($this->data->user === FALSE) {
          redirect();
          return;
        }
      }
    }

    Example Controller

    // Only a logged in user can access the methods within this class
    class Admin extends Admin_Controller {
    
      function __construct() {
        parent::Admin_Controller();
      }
    
      function index() {
        $this->load->view('admin/cpanel', $this->data);
        return;
      }
    
    }
    // Anyone can access the methods within this class, but you still have access to user information.
    class Home extends Public_Controller {
    
      function __construct() {
        parent::Public_Controller();
      }
    
      function index() {
        // Concatenate and upper-case the user's name
        $this->data->display_name = ucwords($this->data->user->first_name . ' ' . $this->data->user->last_name);
        $this->load->view('home/index', $this->data);
        return;
      }
    }

    Finally - our view: showing off our user’s display name:

    Welcome, <?= $user->display_name; ?>.
  • #68 / Jan 15, 2008 3:49pm

    tomcode

    654 posts

    @Michel:

    Doesn’t he need to include the Public_Controller/Admin_Controller ?

    Genre :

    include 'Admin_Controller' .EXT;
    
    // Only a logged in user can access the methods within this class
    class Admin extends Admin_Controller {
  • #69 / Jan 15, 2008 5:28pm

    Kemik

    162 posts

    Hello,

    What’s the benefit of putting that code in MY_Controller? I usually make a function in the controller (e.g. function security, function got_permission, etc) and then call that.

    I’ve checked the userguide as I think I’ve seen MY_ stuff used before but the page below doesn’t go in to much detail.

    http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html

    Edit: This question may be better for a separate thread.

  • #70 / Jan 15, 2008 5:45pm

    tomcode

    654 posts

    What’s the benefit of putting that code ...

    It becomes reusable for several controllers

  • #71 / Jan 16, 2008 9:12am

    flosaurus

    9 posts

    Thank you Mickael.

    Another question an pardon me for my “so little experience” on sessions, authentication process and php in general but just to make sure to understand, why do you check on the
    try_session_login() if there is a session with an user_id corresponding to someone in the user table ?

    my question might be dumb but once again i am quite new to this…

    if i understand, every time i want to display the username on a page, i have to make 2 queries ? one on the session table and one on the user table ?


    Thank you for help

  • #72 / Jan 16, 2008 12:02pm

    Michael Wales

    2070 posts

    tomcode

    Doesn’t he need to include the Public_Controller/Admin_Controller ?

    No, both of those classes are included within /application/library/MY_Controller.php, which is autoloaded if it exists. No need to include() or require() it, CI takes care of it.

    kermik

    What’s the benefit of putting that code in MY_Controller?

    As tomcode said - it makes it reusable. Sure, you could place that code within the __construct() of each class, but then you would have to do it for every class. This way you can accomplish the same with simply an extra 10 characters.

    A more useful setup, and the one I normally use, includes 3 classes: Public_Controller (no login required, user data available if logged in), Auth_Controller (login required, user data available), and Admin_Controller (login required, admin identifier required (usually a database field), and user data available).

    flosaurus

    Another question an pardon me for my “so little experience” on sessions, authentication process and php in general but just to make sure to understand, why do you check on the
    try_session_login() if there is a session with an user_id corresponding to someone in the user table ?

    I believe you are looking at an older version of the code (check out this post for my newest release). I will try to form my response around that release.

    Firstly, ErkanaAuth is developed assuming you are using CI’s Native Session class. It will work with any session class that extends/overwrites the native, but the logic behind some of it’s methods have the native class in mind.

    With the native class, your data isn’t really stored in the database, even if you choose to use the database. Only the data that CI places within the session automatically is stored in the database - all of your custom data still goes into a cookie.

    So, if you want to get some data on the currently logged in user - we’ll need to get his ID. Luckily for us, ErkanaAuth took care of that. When we tried to log the user in (using try_login()) - if it was successful, ErkanaAuth placed the user’s id within the ‘user_id’ session variable.

    So, the following code (which you will find something similar within my Public_Controller and my Admin_Controller) returns a record for the currently logged in user:

    $user = $this->auth->get_user($this->session->userdata('user_id'));

    The get_user() function is flexible though, and can be used for all user’s - not just the logged in user. Let’s say we have a series of posts, and each post has an author_id value. We need to get that author’s username (and we weren’t smart enough to use a JOIN query - lol - it’s an example, get over it). Here’s how that code would look:

    // This imaginary method returns an object of objects, containing my posts
    $posts = $this->posts->get_all();
    foreach ($posts as $post) {
      $author = $this->auth->get_user($post->author_id);
      echo 'Post Author is: ' . $author->username;
    }

    So, all in all, yes - if you are using a class that stores the entire session within the database. Yes, you will end up querying the database twice if you call get_user() passing a session based ID.

    If you are doing that, the only way I can see to reduce your queries is to:
    1) Store all of the user’s data within the session table - a bad idea - and then modify ErkanaAuth to use that rather than the users table.
    2) Extend the session class you are using to JOIN with the users upon selection of the id field.

    Honestly, I don’t think it’s that big of a deal. You should only be calling get_user() once per method for the currently logged in user, so you are merely adding one more database call as overhead (the call to retrieve the user_id from session). If you are calling get_user() more than once, you can definitely refactor your code to eliminate that or even establish a class variable within the parent controllers (the ones that extend Controller) to store the session-based user_id. Then, pass the class variable to get_user() rather than the session call.

    You would still have one extra database call, as overhead, but it wouldn’t be 2 calls each time you are calling get_user().

  • #73 / Jan 16, 2008 12:09pm

    tomcode

    654 posts

    Thanks Michel, I didn’t read carefully enough.

    application/libraries/MY_Controller.php

    Edit 17. january:
    Had only now time to try Your surfin’ the class hierarchy. This is really hot stuff. Thank You man, my controllers look really empty now.

    It’s a pleasure to follow this thread.

  • #74 / Jan 18, 2008 7:02am

    flosaurus

    9 posts

    Thanks a lot michael !
    I’ll stick to your new example and use CI native sessions without database but encrypted cookies.
    Is it enough secure for a small web app ?


    I i understand the process to display the user name (if logged) on a front page i should do like that ?

    Controller : welcome.php

    <?php
    class Welcome extends Public_Controller {
    
      function __construct() {
        parent::Public_Controller();
        $this->output->enable_profiler(TRUE);
      }
    
      function index() {
        if($this->data->user == true) {
        $this->data->display_name = $this->data->user->first_name . ' ' . $this->data->user->last_name;
        }
        $this->load->view('welcome_message',$this->data);
        
        return;
      }
    }
    
    ?>


    View : welcome_message.php

    <?php
    if(isset($display_name)) {
    ?>
    Welcome, <?= $display_name; ?>. 
    <?php
    }
    ?>

    It should show the welcome message when logged and nothing when not logged

    Thanks you for your help

  • #75 / Jan 18, 2008 12:29pm

    Michael Wales

    2070 posts

    That looks pretty good flo - one thing I would look out for is the following line in your code:

    if($this->data->user == true) {

    I'm pretty sure PHP will evaluate this as you expect but logically it's an invalid statement.

    $this->data->user will either be an object, containing user information (if that user exists) or FALSE. So, to be absolutely correct within your code (and avoid any obscure PHP screw-ups), test for FALSE.

    Use the code below:

    function index() {
      // Test for an explicit FALSE (not 0, not unset, only FALSE)
      if ($this->data->user !== FALSE) {
        // We've added first_name and last_name columns to the users table, and since we have a user
        // that data is now in the $this->data->user object. Let's get their full name so we can show
        // it to them.
        $this->data->display_name = $this->data->user->first_name . ' ' . $this->data->user->last_name;
      }
      // Pass the data object to the view
      $this->load->view('welcome_message', $this->data);
      return;
    }
.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases