88
Php

Laravel – 5.0 ACL Using Middleware

Well, actually building an ACL (Access Control Layer) in Laravel is really very easy than using a third party package and I always prefer my own implementation. In Laravel - 4x we’ve used Route Filter mechanism to build an ACL but in Laravel - 5.0 now we have Middleware instead of Filter and it’s much better, IMO.

The idea behind the ACL is that, we want to protect our routes using user roles and permissions and in this case the underlying mechanism is quite same in both versions but only difference is that, in Laravel - 5.0 the Middleware is the layer (for filtering) between our routes and the application, while in Laravel - 4x the Route Filter was used for filtering the requests before the user gets into the application. In this article, I’ll show how it’s easily possible to implement an ACL from the scratch using Middleware.

It’s possible to implement ACL in different ways but this is what I’ve used in Laravel - 4x and also in Laravel - 5.0 and this could be enhanced or improved but approach may varies but the idea is same, filtering user requests before entering into the application layer.
To implement this, we need 4 tables:
  • 1. users
  • 2. roles
  • 3. permissions
  • 4. permission_role (Pivot Table)
Database migration for users table:

Database migration for roles table:

Database migration for permissions table:

Database migration for permission_role table:

These tables are required to build the ACL fields could be changed (add/remove) but to build the relationship between tables we need foreign keys and we can’t remove those fields such as role_id in users table and the pivot table is also necessary as it is.

Now, we need to create the middleware class to check the user permissions and we can create it using php artisan make:middleware CheckPermission from command line/terminal. This will create a skeleton of a middleware class in app/Http/Middleware directory as CheckPermission.php and now we need to edit that class as given below:

Now, we need to create other classes (Eloquent Model) in app/DB directory. Here, in Laravel - 5.0 the models directory is not available and by default the app directory contains the Eloquent model classes such as User but I’ve created the DB directory to house all of my Eloquent/Fluent classes but it’s not mandatory. Anyways, let’s create those classes (User, Role and Permission) now in app/DB or just in app (The full path of User class must be given in the config/Auth.php file).

The traits are used to separate the code in User class to keep the code clean and easily maintainable, (app/DB/User/Traits/UserACL.php trait):

The app/DB/User/Traits/UserRelationShips.php trait (for relationship methods):

The Role class (app/DB/Role.php):

The Permission class (app/DB/Permission.php):

Now, before we can use our Middleware in any route declaration, we need to add it it in the app/Http/Kernel.php file and by default, there are already other middlewares added in that file by Laravel in the $routeMiddleware array and it looks like this:

We’ll just add our middleware at the end of this array like this:

The acl is the alias which we’ll use in our routes when declaring the routes for limited access, for example take a look at this app/Http/routes.php file:

In this file, all of our routes are protected and requires the user to stay logged in (auth is used to check whether the user is logged in or not, available by default in Laravel) and the acl will check if the user has a given permission or not, for example, the dashboard url/route requires the permission manage_own_dashboard because it has 'permission' => 'manage_own_dashboard' and in our middleware we’ll check if the route has the key permission in it’s action and if the value of permission key (which is a permission) is available in the currently logged in users role permissions list then we’ll allow the user to access the application, otherwise we’ll disallow the user access.

On the time, when this article is being written, the Laravel-5.0 framework isn’t released and after the final release, things may change so please make sure you check the updates on Laravel website and hoping, in the first week of January’15, Laravel-5.0 will be released.
How it works?

Actually, this is just a demonstration of only the ACL but I didn’t provide any code which provides an user interface that let’s the admin a way to create user roles by attaching the permissions but only the core idea to implement the ACL in the application.

So, a brief idea is that, each user will be assigned a role when user account is created from the front-end or by the admin (a default role could be set from the back-end) and the roles will be created by admin (super user) from the back-end and permissions will be attached to each roles. So, a role for example Moderator which could have a permission as Suspend User (permission title) and suspend_user (permission_slug) so we can attach suspend_user in a Route using something like this:

So, this route requires the permission suspend_user and in the acl middleware we can check the user’s permission and can protect the route if the user doesn’t has that permission. That’s it.

In this article, I tried discussed how to organize the tables and classes and how to filter the requests using middleware and what classes could be required but not full implementation of a fully functional system, it just gives an abstract idea to create an ACL functionality using Laravel - 5 Middleware from the scratch (without using any third party package).

Since the Laravel-5.0 is still under development, so I didn’t provide the fully functional code here and once the framework is released, then I’ll write another post, maybe in two parts as a series with fully functional code for building an ACL from the scratch, but for now, that’s all. Thank you.

Update:

In my code example, I’ve used menuItem as a key in route declaration. This key is used to build a dynamic menu and to build the menu I’ve created a class/library which is located at app/Libs/Navigation folder of my project. The menu builder class is given below:

Further, to invoke the menu builder class I’ve created a helper function in a helper file which is app/Helpers/fucntions.php and the function is given below:

Finally, I’ve called the function from my view where I wanted to show the menu and the view is a partial of my admin layout which contains following code:

Stay in touch, full (improved code) will be uploaded on github later.


Update: A follow-up of this article for Laravel-5.1.x posted here.

Latest Blog