Laravel Authorization Gate and Policy with Example

Laravel Authorization Gate and Policy
Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Authorization Gate and Policy is one of the fancy features in laravel. Hello Developers. In this tutorial, I will explain about two primary ways of authorizing actions. Which are gates and policies. I will explain from scratch so that you can understand better about Laravel authorization.

Authorization Gates and Policy

 Gates provide a simple, closure-based approach to authorization while policies, like controllers, group 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 tutorial, we will see both Gate and Policy simultaneously with proper examples.

In this tutorial, first I’ll explore gates first and then examine policies. So here we go.

Laravel Authorization Gate and Policy
Laravel Authorization Gate and Policy
Install Laravel

Install a fresh laravel project by the following command.

composer create-project --prefer-dist laravel/laravel gate
Read More : Laravel API Resources & Collections with Examples
 Create a Migration file

By default, Laravel provides us a user migration file. Create a migration file by the following code for creating an extra field in the users table.

php artisan make:migration add_role_column_to_users_table

Now go to the migration file (database/migrations) 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',  ['admin', 'user', 'editor'])->default('admin');
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
           
    }
}

Well, now you have to run php artisan migrate

Define Gates

Well, In this step, I will define our custom gate for user role access. I will define “user”, “editor” and “admin” user. So let’s update the AuthServiceProvider.php file as 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('isEditor', function($user) {
            return $user->role == 'editor';
        });
      
        /* define a user role */
        Gate::define('isUser', function($user) {
            return $user->role == 'user';
        });
    }
}
Use Gate in blade file

Well, Our gate has been defined now I will show how to use the gate in the blade file. In this blade file, I have just shown a silly example.

@can('isAdmin')
  <h1>Only Admin can see this portion!<h1>
@endcan

@can('isUser')
  <h1>Only User can see this portion!</h1>
@endcan

@can('isEditor')
  <h1>Only Editor can see this portion!</h1>
@endcan
How to use Gates in Controller

You can also authorize the user in Controller as like bellow.

 public function create()
    {
        Gate::allows('isAdmin') ? Response::allow()
             : abort(403);

     # Or 
         if (Gate::allows('isAdmin')) {
             dd('Only admin can access this page');
         } else {
             dd('You are not Admin');
         }
        return view('gate.post.create');

      # Or
     if (Gate::denies('isAdmin')) {

        dd('You are not admin');

    } else {
        dd('Admin allowed');
      }
    }
How to use  Gates in Middleware

Also, you can use the gate as middleware. Bellows code I will show you how to use gates as middleware.

Route::get('post', fn () => 'Protected!')->middleware('can:isAdmin')->name('post');

Route::get('/posts/update', '[PostController::class,'update'])->middleware('can:isEditor')->name('post.update');

Route::get('/posts/create', 'PostController@create')->middleware('can:isUser')->name('post.create');

Creating Policies

Well, In this step we will discuss policy. Using policy we can authorize users. Let’s assume 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 post. 

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.

Create a Policy

Well, now you have to create a policy. To do that run the below command in your terminal.

php artisan make:policy PostPolicy

You may specify a --model when executing the command. For your convince look below command.

php artisan make:policy PostPolicy --model=Post
 Register policies

Well, after creating a policy you have to register in the AuthServiceProvider.php file. So go to this file. Inside the policies array, you have to register your policy.

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;
    }
}

In this update method, you can defile your own logic. Here the logic defines that only those user can update their post who is the author of their post. Well, after defining logic you can use policy in middleware, controller, and blade file.

Used policy via Middleware
use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

# Or You can also use it to avoiding models.

Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,App\Models\Post');
How to use Policy in 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...
}
Policy in Blade Template Policy in Blade Template 

Well, now I will show you how to use the policy in the blade file.

@can('update', $post)
    
@elsecan('create', App\Models\Post::class)
    
@endcan

@cannot('update', $post)
    
@elsecannot('create', App\Models\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

The following controller methods will be mapped to their corresponding policy method. When requests are routed to the given controller method, the corresponding policy method will automatically be invoked before the controller method is executed.

Controller Method – > Policy Method

index -> viewAny

show -> view

create – > create

store -> create

update -> update

edit -> update

destroy -> delete

Hope this tutorial will help you.

Read More : Task Scheduling Laravel example with Crontab

Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  

About Anisur Rahman Shahin

Hello. My name is Shahin. I'm a tech enthusiast guy. Personally, I’m Optimistic and always in hurry kinda person. I'm a freelance web developer. I am working at Zakir Soft as Laravel Developer. My Portfolio website: https://devshahin.com/

View all posts by Anisur Rahman Shahin →

Leave a Reply

Your email address will not be published. Required fields are marked *