Laravel Authorization with Gates – Part 1

In this article, we will discuss the “Laravel Authorization with Gates”. As you know, Laravel provided an Authentication solution that is Out of the box. Laravel provides two simple way to manage the authentications such as Gates and Policies. The basic difference between the gates and the policies, Gates provides a simple closure based approach to authorization and policies works around the particular model or resource. Today, we discuss how to implement the Gates in our Laravel Application.

Where we use Gates?

Gates are mostly implemented on the action which is not related to any model or resource. For example the Admin dashboard, we want to allow a user with the admin role can access the admin dashboard. Here, we implement a Gate that verifies user roles and applies restrictions if required.

Prerequisite

We need a copy of the Laravel setup, where we implement our example. I’m assuming, you are familiar with the installation and Laravel setup process so I’m not adding the basic details here. If, you are fresh in Laravel then please check our Laravel articles.

Update User Migration

Here, we have to add the required role to our user table. So open users table migration file located at “database\migrations”.

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->string('role', 50)->default('guest');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

 

Create New Migration for role Column

If, your application is already migrated with the existing migrations. Then you can create a migration for the role column as given below.

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddRoleInUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('role', 50)->default('guest');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('role', 50)->default('guest');
        });
    }
}

 

Update Model

After creating or updating the migrations. You have to add the role column in your user model fillable.

protected $fillable = [
    ... 'role'
];

 

Define Gates

Here, we define multiple gates as per our role base requirement. I’m creating three types of gates such as isAdmin, isEditor, and isGuest.

  • isAdmin – return true if the user role is admin.
  • isEditor – return true if the user role is an editor.
  • isGuest – return true if the user role is guest.
<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        /**
         * Define Gate for admin user role
         * Returns true if user role is set to admin
         **/ 
        Gate::define('isAdmin', function($user) {
            return $user->role == 'admin';
        });

        /**
         * Define Gate for editor user role
         * Returns true if user role is set to editor
         **/ 
        Gate::define('isEditor', function($user) {
            return $user->role == 'editor';
        });

        /**
         * Define Gate for guest user role
         * Returns true if user role is set to guest
         **/ 
        Gate::define('isGuest', function($user) {
            return $user->role == 'guest';
        });
    }
}

 

Use Gate with Middleware

When we define our application routes then we can use the default middleware “can:<GATE_NAME>” as given below.

// Admin Only
Route::middleware('can:isAdmin')->prefix('admin')->group(function () {
    // Mention all admin routes
    Route::get('/', 'AdminController@index');
});

 

Use Gate in Controller

In the controller, there is two way to implements the Gates as per given examples.

In the first example, I’m using the allows method. Using authorize action using gates, Laravel provides two methods such as allows or denies. No need to pass the currently authenticated user to these methods. Laravel handles this automatically and passes the user into the gate closure. You can read the official documentation for more details.

In the second example, I’m using the authorize method. It’s a default method given by Laravel. Like the “can” method, this method accepts the name of the action you wish to authorize and the relevant model. If authorization failed then “authorize” method will throw an exception “Illuminate\Auth\Access\AuthorizationException”, 403 error is present on the screen.

/**
 * Example 1
 * @return Error Message
 */
public function index()
{
    if (\Gate::allows('isAdmin')) {
        echo 'Admin user role is allowed';
    } else {
        echo 'Admin are not allowed not allowed';
    }
}

/**
 * Example 2
 * @return 403 Error
 */
public function index()
{
    $this->authorize('isAdmin'); // return 403
}

 

Use Gate in Blade Template

Laravel provides an easy way to use gates in the blade template. If we want to display a portion of the page when the user is authorized to perform a given action. Here, you can use the “@can” and “@cannot” directives.

@can('isAdmin')
    <h2>Admin View</h2>
@elsecan('isEditor')
    <h2>Editor View</h2>
@else
    <h2>Guest View</h2>
@endcan

 

Conclusion

In this article, we are discussing the Laravel Authorization with Gates. I’m trying to explain the Laravel Gates in a simple and easy way. Hope you like this article, feel free to add your comments if any query. You can submit your feedback too. In our next post, we will discuss Laravel Authorization with Policies and many more.

You may like:

Laravel Default Authentication Setup

How to Use Make Auth in Laravel 6

If you like our content, please consider buying us a coffee.
Thank you for your support!
Buy Me a Coffee

LaravelLaravel 5.8Laravel 6
Comments (3)
Add Comment
  • Renan

    Hi, if the route can be access by admin and an editor, I’m trying this but it’s not working, like
    middleware(‘can:isAdmin, isEditor’)
    Can you help ?

    • 123123

      middleware supports array, so use:
      middleware([‘can:isAdmin’, ‘can:isEditor’])

  • Nab Roshyara

    Hi 🙂
    // Admin Only
    Route::middleware(‘can:isAdmin’)->prefix(‘admin’)->group(function () {
    // Mention all admin routes
    Route::get(‘/’, ‘AdminController@index’);
    });
    is not working.
    It works only if you write
    Route::middleware(‘can:isAdmin’)->group(function () {
    // Mention all admin routes
    Route::get(‘/’, ‘AdminController@index’);
    });