When you decide to work with PHP and MySQL you probably end up creating some sort of user controlled application. It might not be your first application but rather soon you start working with forms and suddenly you have created a login form and want to validate the user on every single page to see if the user is allowed to view the page content. Today I will present my PHP Authorization Class.

The authorization class will not take care of a login script or anything validating a user trying to login on your application. If you need a easy and fast login script you can read all about that on my SQL Login post. This class will take care of the page validation you need to do to make sure the logged in user is valid. This is done by introducing three different types: roles, resources and actions.

A role represents a user group for example guest, member, staff or moderator. A resource is easily explained as an object such as news, articles, users or games. Lastly the action is something you want to do such as add, delete, edit, view or list. With these three types we are able to specify authorization rules for various roles.

“Hum, I still don’t get it!”

The PHP Authorization Class will help us define and set up rules for different roles. We can apply various action rules onto our resources which are, in the end, connected to our roles. We take a look at a example. Say we have three different roles defined for our application:

  • guest – a visitor on the site which are not logged in.
  • member – a logged in visitor.
  • admin – the administrator

To simplify our application we only have one resource on the site which is:

  • news

If we look at the overall actions we would like to do with this resource we might end up with something like this:

  • view – look at a specific news item
  • list – look at all news items presented as a list
  • add – add news
  • edit – edit news
  • delete – delete news

Going back to our roles, we don’t want to let the guest role adding, editing nor deleting news. In this example we don’t even let guests view a specific news. As for a member they should be able to view, list and add news. The administrator should be able to do everything. We can achieve this by writing something like this:

$authorization = new Authorization();
$guest = 'guest';
$authorization->addRole($guest);
$authorization->addAccess('news', $guest, 'list');

$member = 'member';
$authorization->addRole($member, $guest);
$authorization->addAccess('news', $member, array('view', 'add'));

$admin = 'admin';
$authorization->addRole($admin, $member);
$authorization->addAccess('news', $admin, array('edit', 'delete'));

The above code implements the description of rules we stated a bit further up. We made a DSL to implement our authorization class if you will. Let’s look at the code in more detail to see if we find anything interesting.

$authorization = new Authorization();

We create our PHP Authorization object and assign it to a variable named authorization.

$guest = 'guest';
$authorization->addRole($guest);
$authorization->addAccess('news', $guest, 'list');

We assign the variable guest the value of ‘guest’. Then we add that variable to our list of roles our authorization class holds. The third line adds access rules. We start with providing the resource, the role and lastly the action. We could skip the first line and just add ‘guest’ instead of $guest. So, to make this very clear: These three lines of code gives the user group/role guest the ability to list all news on the site.

The next two sections are very similar to the first except for two things:

$authorization->addRole($member, $guest);
$authorization->addAccess('news', $member, array('view', 'add'));

In the first section the addRole method only took one argument and here we have two. What does this mean? It means that the first argument will be extended with the second argument. In this case, member will be extended with guest. This is really useful if member should have the same access as guest plus a few more. We don’t need to add the list action to member because guest already has it. Basically guest is the parent of member (which is acting like a child). Everything we add to guest is also added to member even if we decide to assign more rules to guest after we have defined and created the member role. Pretty sweet huh?

The other thing that differ is the number of actions you can provide to the addAccess method. You can add just one action as a normal string or provide an array of actions. Also very useful if a resource has a lot of different actions defined.

So, the code above created our three different roles and we applied different action access for each of the roles on our news resource. Now we are able to query our Authorization class to see if a specific role have access to a specific resource with a specific action. We do this by using the isAllowed method.

echo $authorization->isAllowed($guest, 'news', 'list') ? 'allowed' : 'denied';

What do you think? Is guest allowed to list the news? The answer is yes. Can answer these:

echo $authorization->isAllowed($member, 'news', 'list') ? 'allowed' : 'denied';
echo $authorization->isAllowed($member, 'news', 'add') ? 'allowed' : 'denied';
echo $authorization->isAllowed($admin, 'news', 'add') ? 'allowed' : 'denied';
echo $authorization->isAllowed($admin, 'news', 'list') ? 'allowed' : 'denied';
echo $authorization->isAllowed($admin, 'news', 'comment') ? 'allowed' : 'denied';

And the answers:

Yes, member is extended with guest and guest is allowed to list news.
Yes, member is allowed to add news.
Yes, admin is extended by member and member is allowed to add news.
Yes, admin is extended by member and member is extended by guest and guest is allowed to list news.
No, admin is denied to comment on news.

Pretty cool! This can be used in your PHP pages where you need to check if the user is valid. For example in your header file to make sure unauthorized users don’t get access to your pages and files. To know if you should add a comment form or not you simple check if the role in question have the access to comment. You are able to be very specific and you can show different parts of the page depending on the role type.

Since the class doesn’t require a database it’s 100% customizable. You can add your very own roles, resources and actions. All of this sounds pretty nice but how would it work in real action? I will give you a sweet example.

To be able to check if the role has access to the resource with a specific action we need to know the role, the resource and of course the action. It might sound like a huge amount of effort to get this to work, but it isn’t! The specific role needs to be fetch from the user in question. Let’s say we have a database with users and each user has a access type, say A-C. Either you can use these values straight of as your roles or we can translate them to understandable roles: A = guest, B = member and C = admin. This can then be saved in a session or in anyway you know as long as you are able to access it often and fast. The get our hands on the resource and action we can use the splendid mod_rewrite found in the Apache server software. If you don’t know what this module does, I suggest you take a peak at my other post about friendly URL’s. If we use the .htaccess wisely we will be able to fetch the resource and action from our URL.

.htaccess example:

RewriteEngine on
RewriteRule ^([a-z_]+)$ /authorization/$1/ [R]
RewriteRule ^([a-z_]+)/$ /authorization/index.php?resource=$1&action=list
RewriteRule ^([a-z_]+)/([a-z_]+)$ /authorization/$1/$2/ [R]
RewriteRule ^([a-z_]+)/([a-z_]+)/$ /authorization/index.php?resource=$1&action=$2

In this example my root is /authorization. The first two rewrites takes care of an example looking like this:

http://www.dosspot.com/games

It will first add a / to the end and reload and send the user to my index page with two get variables resource and action. We we haven’t added an action the default action is list. The other two rules are activated if we have applied an action to.

http://www.dosspot.com/games/view/

Now we are able to fetch the resource and action out from our GET array and see if the role is valid for this page. If not we send him/her of to another page. So now we have two examples where we use the Authorization class inside a page using the isAllowed method to see if the user in question should be able to do various actions. Or we can use the URL to fetch the resource and action in question and validate. In our index.php page it might look something like this:

if(isset($_GET['resource']) && isset($_GET['action'])) {
$resource = mysql_real_escape_string($_GET['resource']);
$action = mysql_real_escape_string($_GET['action']);
$role = $_SESSION['role'];
}

if($authorization->isAllowed($role, $resource, $action)) {
echo 'You are allowed';
} else {
echo 'You are not allowed in here!';
}

Pretty simple put yet effective. But! There is more to it! Now we have a set of methods we can use to grant access to resources with different actions. If a user doesn’t have the access s/he is thrown out from that page. We might want to apply a few of these access rules to every role avaible and we don’t want to use extend, because there might just be one access we want to share, and we don’t want to write it twice. How can we do this? Simple, we add null instead of a role in the addAccess method. By supplying null as the role the access rule will be applied to all roles, including roles added after the null access.

So let’s say we want our guest to be able to access both the list and add news. The member role should just be able to list, not add. In this case we cannot extend the member role with the guest role since then the member role would be able to add news. Here is some code:

$authorization = new Authorization();
$authorization->addAccess('news, null, 'list);

$guest = 'guest';
$authorization->addRole($guest);
$authorization->addAccess('news', $guest, 'add');

$member = 'member';
$authorization->addRole($member);
$authorization->addAccess('news', $member, 'view');

With this slightly different code everyone will be able to list the news but the guest will be the only one able to add news and member the only one able to view a news. If this would be a real case it would be very bad, in this example though it shows the example pretty well. Notice that member isn’t extended by the guest role.

The next thing we might be interested in is how we save the authorization object. We can do this with a simple session or we can store it using the serialize method in PHP. Since we have been working with session before we are going to use the serialize technique. Basically we are able to serialize an object meaning that we are able to save it on a file. We can then just unserialize the file and get our object back. By doing this we can write our authorization code in one file, serialize it and remove that code. Since the object is stored in a file we don’t need to create our object everytime we want to access it, we just unserialize the file and the object with it’s current state it presented to us. Sadly I’m a newbie working with the serialize method so if you know any problems or errors working with it, please let me know.

We simply use the save() method in the Authorization class to serialize our authorization object. We are able to provide a filename, by default it’s saved as authorization. With our .htaccess file we are able to block everyone out from this file and deny everyone trying to access it. In every page we want to validate the user we simple do this:

include('Authorization.php');
$object = implode("", @file("authorization"));
$authorization = unserialize($object );

We have to include the class file and then we read the file and finally use the unserialize method to unserialze the object and we assign it again to our authorization variable. Now we are able to use the object exactly the same as we did in the examples above. Combine this with the .htaccess rewrite options you will find it rather easy to control the visitors using your system. It’s easy, straight forward and pretty cool!

The download below provides everything you will need to run the authorization class, including unit tests!