Laravel 9 Gates And Policies Tutorial With Example

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');

 

Creating Policies

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