Skip to content

joeflintham/rbac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RBAC Bolt-on

This RBAC bolt-on is a php-based user authentication system with role-based access control. It is intended as a tool to help while building prototype web-apps which need to authenticate users and provide access rights for various actions.

The RBAC bolt-on is designed to be a quick, hackable way to add role-based user-authentication to an app during prototyping. For production deployment, you'll likely want to beef up the security. For the build process, it can be convenient to test user authentication and permissions using this bolt-on, because it can be added on to your project with just a few lines of code, and then utilised through a number of methods.

What's this for?

I find when I'm building an app, I'm likely to have very specific requirements about user authentication and permission checking; however, what I really want to do is build the app, not a user authentication system! So I use this bolt-on as a temporary solution while developing and testing my app's functionality with authenticated users. When my development phase is ready, I can then implement a bespoke RBAC for the app.

Requirements

  • PHP 5.3+
  • MySQL 5

Usage

Once installed, you can initialise a static object which represents the current user. After including the necessary files, initialise the user as follows:

<?php

require_once ("config.php");
require_once ("UserSystem/User.php");

// initialise user

User::setupUser();

?>

Then you can authenticate a user in one of four ways: GET, POST, COOKIE or SESSION. Populating any of these data objects with the following parameters:

  • user_name - the user name
  • user_password - the user password

e.g. you can call your php page with a GET query string of the form

/foo/bar/?user_name=yourusername&user_password=yourpassword

This will also set the php SESSION variable (if active using session_start()) and set a COOKIE (if enabled) keeping your user logged in until you pass in a GET or POST variable called "logout".

In your php script, you can access your user's properties using the static method getUser().

User::setupUser();

if (User::getUser()->authenticated){ /* logged in user actions */ }

Permissions

There are several default user types that are set up in the RBAC bolt-on. These are:

god: a notional user with impossible powers. included for conceptual purposes; don't use unless you want to create permissions that should never be used. ;-)
superuser: the top level user, who has all permissions
admin: an administrator who can usually perform CRUD actions (Create, Read, Update, Delete)
contributor: useful to assign to user who can create and edit their own items
member: authenticated users with read-only access
guest: unauthenticated users
nobody: a default user with less than no permissions. Used during setup.

Note that these user_types are all optional and can be interpreted / implemented as you wish.

If you want to use the RBAC system, you will need to populate the permissions database with keys that you wish to test for, and for each key, a permission level corresponding to the user_type who has permission to perform the action. Once you've done this, you can test whether the currently authenticated user has permission to perform such actions with the following code:

User::setupUser();

if (User::getUser()->authenticated){ 
   /* logged in user actions */ 

   $permission = 'action_to_perform'; // 'action_to_form' should be a known value in the Permissions table
   if (User::getUser()->hasPermission($permission)){
      /* user has correct access privileges */
   } else {
      // polite rejection message?
   }
} else {
   // redirect to login?
}

Permission cascading

In order to keep the RBAC bolt-on as simple as possible, it is assumed that members of a higher rank inherit all the privileges of lower-ranking user_types. Hence, the superuser has all the permissions of the admin, contributor, member and guest types. A consequence of this is that each user type could be permitted to edit the user_type of lower-ranking users (e.g. a contributor could change a member into a contributor). Of course you can utilise or override this behaviour by planning your permissions table carefully.

Permission planning

The best way to illustrate permissions is to look at an example from a recent prototype built using Slim PHP (which currently has no mature user-auth or RBAC interface).

Slim uses 'routes' to determine the webapp's functionality; we used the route as the key in the permissions table to maintain ease of use.

$app->get('/foo/bar/', function () use($app) {
    if (User::getUser()->hasPermission('/foo/bar/')){
        /* user has permission */
    } else {
        // user not permitted: is it because they're not logged in?
        if (!(User::getUser()->authenticated)){
	    /* redirect to login form */
        } else {
	    /* redirect to polite rejection */
        }
    }
});

Installation - short version

First steps (more details follow beneath the initial list):

  • publish the RBAC directory contents to a web-accessible location
  • create a MySQL database and user account
  • edit config.php
  • run the setup process
  • add a real user
  • set up the permissions table

Installation - walkthrough

Setting up your database: you can use phpMyAdmin; easier to use the mysql CLI. This example uses the database name 'rbac', the db username 'rbac_user' and the password 'rbac_pass'. Substitute with your own.

$ mysql -u db_admin_username -p
[enter db admin password at prompt]
mysql> create database rbac;
mysql> grant all on rbac.* to rbac_user@localhost identified by 'rbac_pass';

Edit config.php to reflect the database / credentials you used above. If you don't have CLI access to mysql, consider changing your host.

Now create a temporary php script to intialise the database (there is one included in the package, 'index.php', which should be removed after use). Assuming your php script is called 'index.php', point your browser at:

http://your.domain.com/path/to/rbac/index.php?user_name=nobody&user_password=nobody

On first run, this will create the necessary tables for your users and permissions.

You now have a user table with a nobody user; and a permissions table with one demo permission for reference.

Creating users

If you want to get up and running with some test users quickly, you can add them at the mysql CLI. The table only stores sha1 password hashes, so your insert comand should look something like this:

mysql> insert into users (user_name, user_password, user_displayName, user_type) values ('joe', '16a9a54ddf4259952e3c118c763138e83693d7fd', 'Joe', 'member');

The above example inserts the user joe with password 'joe'. To create a sha1 password hash, use the php interactive shell. Here we generate a sha hash for 'password' - substitute your own:

$ php -a
echo sha1('password');

You can then copy and paste the resultant hash into your mysql command.

The RBAC User object also has methods for creating, editing and deleting users.

User::createUser(array(
    "user_name"         => "",
    "user_password"     => "",
    "user_displayName"  => "",
    "user_type"         => ""
));

User::editUser(array(
    "user_name"         => "",
    "user_displayName"  => "",
    "user_type"         => ""
));

User::changePassword(array(
    "user_name"         => "",
    "user_new_password"  => "",
    "user_new_password_repeat"  => ""
));

User::deleteUser(array(
    "user_name"         => ""
));

All the above commands return Boolean:True on success, and an ErrorHandler object on failure. The ErrorHandler object has a public property listing one or more error messages:

$response = User::editUser(array(
    "user_name" => "",
    "user_displayName" => "",
    "user_type" => ""
)); // fails for all three values, returns ErrorHandler object

if (is_object($response)){
   print_r($response->messageList); // spits out array of error messages
} else if ($response) {
   // success
}

Set up permissions

Using the mysql cli or phpMyAdmin, add the permissions and roles associated with them to the Permissions table. e.g.

mysql> insert into permissions (permission_description, permission_reference, permission_level) values ('Example permission','demo','superuser');

The above record allows you to test whether the current user has permission to complete and action with the following code:

    if (User::getUser()->hasPermission('demo')){ // user must be a superuser
        /* user is a superuser, has permission */
    } else {
        // user not permitted
    }

Notes

  • Remove index.php after use
  • Don't use in production (savvy users can log in by hacking cookies and sessions, albeit only if they already have credentials, and you probably want to direct them through specific routes for analytics, conversion, etc)
  • If you're already using a DB class you should find it easy to wrap the User and Permissions classes around that instead of the DB class used here.

About

Role-based access control user authentication bolt-on

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages