Hello artisan,
In this tutorial, I will show you two primary ways of authorizing actions: gates and policies in the Laravel 9 application. You know that using gate and policy, we can authorize users in Laravel. I will explain from step by step so that you can understand better about Laravel authorization using gate and policy. You need to follow this example to learn Laravel Authorization Gates and Policies Example.
In Laravel, Gates provides a simple, closure based approach to authorization while policies, like controllers, group their logic around a particular model or resource. If you compare Gate and Policy, Gates are most applicable to actions that are not related to any model or resource, such as viewing an administrator dashboard.
In this example, we will compare also laravel gates vs policies with source code. In this example tutorial, I'll explore gates first and then examine policies. So let's start.
Step 1: Install Laravel
Download the fresh laravel app to start it from scratch by the following command.
composer create-project --prefer-dist laravel/laravel blog
Step 2: Create Migration
In this step, I will create a new migration to add a new column for "role". we will take enum datatype for the role column. I shall take only the "user", "manager" and "admin" values on that. we will keep "user" as the default value.
php artisan make:migration add_role_column_to_users_table
Now open this migration file and paste the below code.
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddRoleColumnToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->enum('role', ['user', 'manager', 'admin'])->default('user');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}
Now run migrate to add this table.
php artisan migrate
Step 3: Define Gates
In this step, I will define our custom gate for user role access. I will define "user", "manager" and "admin" user. So let's update the AuthServiceProvider.php
file as like below:
app/Providers/AuthServiceProvider.php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
/* define a admin user role */
Gate::define('isAdmin', function($user) {
return $user->role == 'admin';
});
/* define a manager user role */
Gate::define('isManager', function($user) {
return $user->role == 'manager';
});
/* define a user role */
Gate::define('isUser', function($user) {
return $user->role == 'user';
});
}
}
Step 4: Use Gates in Blade File
Now, here user our custom gate in our blade file. We have created three buttons for each role. When the user will try to log in then the user will see only the user button and the same way for others.
resources/views/home.blade.php
Now you can check it by creating three types of user and after login you will be able to see the output of this authorization using gate and policy tutorial in laravel.
Step 5: Use Gates in Controller
You can also authorize the user in Controller as bellow:
public function delete()
{
if (Gate::allows('isAdmin')) {
dd('Admin allowed');
} else {
dd('You are not Admin');
}
}
/**
* Create a new controller instance.
*
* @return void
*/
public function delete()
{
if (Gate::denies('isAdmin')) {
dd('You are not admin');
} else {
dd('Admin allowed');
}
}
Step 6 : Gates in Middleware
We can use user roles with middleware as like below:
routes/web.php
Route::get('/posts/delete', 'PostController@delete')->middleware('can:isAdmin')->name('post.delete');
Route::get('/posts/update', 'PostController@update')->middleware('can:isManager')->name('post.update');
Route::get('/posts/create', 'PostController@create')->middleware('can:isUser')->name('post.create');
Now in this step, we will discuss policy. Using policy we can authorize users. Just think you will allow the user to see their own post. At this time we can use the gate to allow users to see their own created posts.
In Laravel Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have a Post
model and a corresponding PostPolicy
to authorize user actions such as creating or updating posts.
Step 7 : Create Policy
Run the below command to create a policy.
php artisan make:policy PostPolicy
You may specify a --model
when executing the command:
php artisan make:policy PostPolicy --model=Post
Step 8: Register policies
In this step, we need to register our policy before using it. So register it in the following file:
app/Providers/AuthServiceProvider.php
namespace App\Providers;
use App\Policies\PostPolicy;
use App\Post;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
Once the policy has been registered, we may add methods for each action it authorizes in PostPolicy class like below.
app/Policies/PostPolicy.php
namespace App\Policies;
use App\Post;
use App\User;
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
Here the logic defines that only those user can update their post who is the author of their post. Now you can check it like below.
if ($user->can('update', $post)) {
//user is authorized now
}
Step 9: Used policy via Middleware
Laravel includes a middleware that can authorize actions before the incoming request even reaches your routes or controllers, check the below code to understand.
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
You can also use it to avoid models.
Route::post('/post', function () {
// The current user may create posts...
})->middleware('can:create,App\Post');
Step 10: Controllers Helpers
You can use the policy class method to authorize users like below.
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}
The following controller methods will be mapped to their corresponding policy method:
Controller Method | Policy Method |
---|---|
index | viewAny |
show | view |
create | create |
store | create |
edit | update |
update | update |
destroy | delete |
Step 11: Policy in Blade Template
In this situation, you may use the @can
and @cannot
family of directives:
@can('update', $post)
@elsecan('create', App\Post::class)
@endcan
@cannot('update', $post)
@elsecannot('create', App\Post::class)
@endcannot
Like most of the other authorization methods, you may pass a class name to the @can
and @cannot
directives if the action does not require a model instance:
@can('create', App\Post::class)
@endcan
@cannot('create', App\Post::class)
@endcannot
Read also: User Roles and Permissions Tutorial in Laravel without Packages
Hope this Laravel Gate and Policy tutorials will help you to learn new things. So you can authorize users to use the gate or policy which you want to use in your application. According to the situation demand hope you will be able to use these awesome features.
#laravel #laravel-9x #laravel-authorization