Welcome Guest, Not a member yet? Register   Sign In
Developping user authentication.
#1

[eluser]Bramme[/eluser]
Hello everybody

Long time!

Okay, so I've got a rather theorethical question for you guys. I want to make an efficient user authentication library that allows me to control user(group) rights. I don't want to hard code policies as I want to be able to add usergroups and change the policies on the fly through a CMS page (like you can in Drupal for example).

This is the workflow I used in the past: every method that needed user control got a comment with a specific markup. I had a function that would parse my controller files, looking for those comments, format them and store them in a db table. That way, I had all my methods stored in the database. Then it was just a matter of storing who's allowed to what function.

This worked, however, the comment, the file parsing, the manually having to run the function everytime I added a function... It didn't and still doesn't feel right.

So I'd like some hints, tips, insights on how to actually make this work better. Anyone got an idea?
#2

[eluser]WanWizard[/eluser]
We use a task-based RBAC model.

Every item or event in the system has a task assigned to it. Menu links, pages, specific activities (p.e. add/edit/delete), etc. You can assign users, groups and roles to a task, users to groups, users to role, groups to other groups (subgroups) and roles to other roles (subroles).

An RBAC library extracts the information from the database, unifies it, and stores it with the task_id as index. I'm thinking about caching this, so we don't have to do this for every page request.
The RBAC library has a method has_task_assigned(), which you feed a task identifier, and returns a boolean, and which is called by every controller that wants to enforce access rights.

Quite complex, I admit, but the only model we could come up with that allowed for maximum flexibility.

Also, we don't have one of the downsides you mentioned, tasks are automatically generated, either through user interaction (creation of a new page or menu item), or by installation of a new module (in which case the module installer knows which tasks to add).
#3

[eluser]Bramme[/eluser]
Thanks for the reply.

But if I get it right, you're still storing your tasks in a database? They just get added dynamically by creating a page (that is also stored in a db I guess?) or by running a query when installing a module?
#4

[eluser]WanWizard[/eluser]
Yup (on all observations).

By lack of a better solution, because clearly it requires quite a few queries, and since you have to do this for every page request, it's a database load i'd like to avoid.
Unfortunately, flexibility comes with complexity, (see the database model) and we haven't had a eureka moment yet.

I'm interested to see where this discussion will lead...
#5

[eluser]Bramme[/eluser]
The framework at my job uses an interesting method (though I still don't quite understand, should ask the lead programmer better info :p).

Basically, our application has a huge baseclass that has methods for basic CRUD things. Every CRUD set has it's own physical file in a separate folder (Blog/Bloglist, blog/blogcreate, blog/blogedit, blog/blogdelete) that use an instance of the base class. The create, edit and delete files just reference the list file actually. If a page needs a different view than the standard list, we just overwrite the showlist() method in the list file.

This apparently also makes it easy to control who's allowed to what page, though come to think of it, this would mean that the application has to loop through all the folders and files everytime :/ Seeing as that's over 600 files, I can't imagine that being effective.

Anyhow, our user authentication works like a charm. The rest is quite a bitch :p
#6

[eluser]flaky[/eluser]
well, what I've done is declare an array in every controller that contains all the names of the methods sth like this
Code:
$methods = array('index', 'add', 'edit', 'delete', 'details', 'hide');

in my modules controller when I access the controller it reads the array, and does the updates accordingly to the data it obtains. By no way it is perfect, but it works.

cheers
#7

[eluser]nuwanda[/eluser]
I may be missing something, but what's wrong with simply storing a user level or group in a session car and then testing it for access? The CI index() processes this.

This is what I see in simple and complex open source apps, and it seems to work fine.
#8

[eluser]Bramme[/eluser]
[quote author="nuwanda" date="1276691589"]I may be missing something, but what's wrong with simply storing a user level or group in a session car and then testing it for access? The CI index() processes this.

This is what I see in simple and complex open source apps, and it seems to work fine.[/quote]

Could you elaborate on this, as I don't fully understand what you mean?
#9

[eluser]nuwanda[/eluser]
Well, I have a helper that has is_logged_in() and is_admin() functions in it. The helper is autoloaded so it's available to all controllers.

They simply test for the session status of a user, then I allow access to that controller, or redirect. This happens in the CI index function for the controller, which gets executed before anything else in the class.

But I could have a function like is_editor() or similar. The session var is set during login.

Code:
function is_admin()
{
  $CI =& get_instance();

  if(isset($_SESSION['user_role']) AND $_SESSION['user_role']=='admin')
    {
      return TRUE;
    }
  else
  {
      return FALSE;
  }
}

So in my admin pages I have:

Code:
function index()
  {
    //check if admin
    if(!is_admin())
    {
      redirect('site');
    }

    $this->show_admin_dashboard();
  }
#10

[eluser]WanWizard[/eluser]
Simple apps use a single user level value to indicate the status of a user. Like 0 = public, 10 = member, 100 = admin, etc. A certain level gives also access to lower levels, so an admin has access to all member and public pages as well.

For any more complicated application, this method is useless. It gets complicated if you have pages that a member can see but an admin not, or if you need to differentiate between members.

If I look at ExiteCMS, I have blog authors (members that are allowed to create blog entries, and edit their own), blog editors (may edit all blogs), blog admins (may also delete, move, and change author). I have forum readers (those than can read messages in a forum), forum posters (have write access), forum moderators (may edit other peoples posts) and forum admins (may move posts and threads). And this list goes on and on.

The only way to deal with this, and keep it scalable, is to use role based access.

So I have a role 'Blog editors', and anyone assigned this role can edit blog entries. This role is also assigned to the role 'blog admins', so admins inherit all rights assigned to editors. Since not every aspect of rights management can be defined by roles, ExiteCMS also supports groups, which is is a arbiterary list of users. Like all French users. Or all users between 30 and 40 years old. I can then assign the group roles, p.e. 'French community access' to the group of French users. A new user from France gets assigned to the group, and immediately has all rights needed.




Theme © iAndrew 2016 - Forum software by © MyBB