Let's see how to set up a simple role-based authorization system in Laravel 8.
In this tutorial, I'll set up a single-role-based system but you can expand the same to a multi-role-based one. Similarly, I'll be pulling the roles and permissions from an array instead of a database. We will implement authorization using gates.
I plan to cover a more advanced version of the same in the future but I believe, understanding a concept is much easier when it is simplified and to the point. I'll recommend going through Laravel 8 authorization docs once before reading this article.
You can view all the source on my GitHub repo, which is slightly modified for demonstration.
About our Application
In order to explain, I'll be creating an application with 3 roles - admin, manager & customer. And our permissions will be based around products - creating, updating, viewing, deleting. While managers & admins have all permissions, customers should only be able to view.
Getting Started
Once you have installed and set up Laravel. We'll scaffold authentication using the PHP artisan ui bootstrap --auth
command followed by npm install
& npm run dev
.
You can do so with any of the other authentication scaffoldings you are familiar with and adjust accordingly.
Adding Role to Migration
Open up the create_users_table_table
migration file in database/migrations
.
We modify the scaffolded schema and set up a role column that will store a string and will have 'customer' as the default value.
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('role')->default('customer');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Setting up our Authentication Mechanism
Open AuthServiceProvider
inside app/Providers
. Let's add a permissions array to the class within.
public static $permissions = [
'index-product' => ['manager', 'customer'],
'show-product' => ['manager', 'customer'],
'create-product' => ['manager'],
'store-product' => ['manager'],
'edit-product' => ['manager'],
'update-product' => ['manager'],
'destroy-product' => ['manager'],
];
What's going on here? This is an array in the form of $action => $roles[]
.
Setting our Gates
We modify the boot() function with our logic.
public function boot()
{
$this->registerPolicies();
// Roles based authorization
Gate::before(
function ($user, $ability) {
if ($user->role === 'admin') {
return true;
}
}
);
foreach (self::$permissions as $action=> $roles) {
Gate::define(
$action,
function (User $user) use ($roles) {
if (in_array($user->role, $roles)) {
return true;
}
}
);
}
}
Here, using Gates:before()
we allow the admin access to all abilities by returning true
if user role is admin.
Next, we loop through our permissions array and define a gate for each. Where in, we check if the role of the user is in the roles associated to the actions.
We have basically mapped our permissions array to gates.
Using our Authorization System
With everything all set, we can now use the system.
In our Controllers
By using the authorize()
method.
$this->authorize('update-product');
In our Models
By using the can()
method.
$this->can('update-product');
In our Views
By using the @can
blade directive method.
@can('update-product')
//
@endcan
Via our Models
By using the can()
method.
if ($user->can('update-product')) {
//
}
Via Middleware
By using can:action-name
middleware.
Route::put('/product/{Product}', [PostController::class, 'update'])->middleware('can:update-post');
That's All
This article should have given you a general idea of how you can create an authorization system. While this is basic, you can add to & improve the implementation to support the features you need.
Liked what you read? Support me here: https://www.buymeacoffee.com/zaxwebs
Top comments (6)
good
and also whats the advantage you using Array
There are other methods that are far better than an array. But for the sake of keeping it simple for the tutorial, I used an array.
where i can found boot() function
"AuthServiceProvider inside app/Providers" :)
awesome!