Laravel 8.x Gate And Policy Example From Scratch

Hi devs, in this tutorial i will explain about two primary ways of authorizing actions: gates and policies in Laravel. I will explain from scratch so that you can understand better about Laravel authorization using gate and policy. You have to just follow this tutorial to learn Laravel Authorization Gates and Policies Example.

Think of gates and policies like routes and controllers. Gates provide 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 which are not related to any model or resource, such as viewing an administrator dashboard. In this tutorial we will see both like Gate and Policy simultaneously with  proper example.

In this example tutorial i'll explore gates first and then examine policies. So let's start.

 

Step 1: Install Laravel

Download 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 new migration to add new column for "role". we will take enum datatype for role column. I shall take only "user", "manager" and "admin" value on that. we will keep "user" as default value.

php artisan make:migration add_role_column_to_users_table

 

Now open this migration file and paste this 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 AuthServiceProvider.php file as like bellow:

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 button for each roles. When user will try to login then user will see only user button and 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 user in Controller as like 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 bellow:

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 about policy. Using policy we can authorize users. Just think you will allow user to see their own post. In this time we can use gate to allow users to see their own created post. 

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 below command to create 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 use 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 are 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 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 avoiding models.

Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,App\Post');

 

Step 10: Controllers Helpers

You can use policy class method to authorize user 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 using gate or policy which you want to use in your application. According to situation demand hope you will able to use this awesome features.

 

#laravel #gates #policy #laravel-6 #laravel-7 #authorization #access-control