LARAVEL-8 AUTHORIZATION

The approach for authorization in Laravel is quite simple and easy. In this blog, we will talk about LARAVEL gates and policies for authorization. After introducing the terms like authorization, authentication, gates, and policies, we will implement the concepts with an example. But before that, let’s understand the terms we will use in this blog of LARAVEL authentication.

What is Laravel authentication?

Laravel authentication is used to identify the user credentials and is managed by sessions that take the input like email or username and password for user identification.

How to authorize?

In Laravel, you have two ways to authorize a user. These are:

  • Closure based approach 
  • Class-based approach

The closure-based approach of authorization is called Gates, and the class-based approach is called policy. In this document, we will tell you to authorize using both gates and closure-based routes.

What is the difference between authorization and authentication:

As the name suggests, authentication confirms the identity of the users or makes sure they are what they claim to be. Meaning, a user can only work on those modules and actions which have been allowed to them.

Both authentication and authorization are distinct security processes in the world of identity and access management (IAM) in Laravel 8. However, authorization permits the right users to access the resources. We will talk about this in detail in a later part of the document. 

Gates vs. Policies in Laravel:

Laravel Gates and policies are like routes and controllers, respectively. Gates allows users to define an authorization using a simple closure-based approach. If you want an action unrelated to any specific model, gates are perfect to use.

Gates must have a user instance as its first argument and may optionally have additional arguments as a relevant Eloquent model. So, now you know how to use gates to authorize actions in your Laravel application. 

The next section is all about updating an article:

<?php

use App\Models\Article;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

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

    Gate::define('update-article', function (User $user, Article $article) {
        return $user->id === $article->user_id;
    });
}

The Gates are defined in the boot method of the App\Providers\AuthServiceProvider class, and it uses the Gate facade. 

Let’s understand this with an example, where a user can update an article Model App\Models\Article; the gate will do this by comparing the user’s id against the user_id that created the article. Please see the example below:

<?php

use App\Models\Article;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

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

    Gate::define('update-article', function (User $user, Article $article) {
        return $user->id === $article->user_id;
    });
}

How to authorize actions in Laravel 8:

We can authorize actions using gates in Laravel 8. You can use “allows” or “denies” methods profiled by the Gate facade. We don’t need to pass the currently authenticated user to these methods, laravel will automatically pass the user into the gate closure. We need to call gate authorization methods within the application controllers before performing an action that requires authorization.

Please see the example below:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController extends Controller
{
    public function update(Request $request, Article $article)
    {
        if (! Gate::allows('update-article', $article)) {
            abort(403);
        }

        // Update the article code here...
    }
}

The above code check for the user if he is allowed to perform the action, And if you want to determine if a user other then the currently authenticated user is authorized for the action then need to use for user method on the Gate facade:

<?php

if (Gate::forUser($user)->allows('update-article', $article)) {
    // The user can update the article...
}

if (Gate::forUser($user)->denies('update-article', $article)) {
    // The user can't update the article...
}
To authorise multiple action, we need to pass and array of methods:

if (Gate::any(['update-article', 'delete-article'], $article)) {
   // The user can update or delete the article
}

if (Gate::none(['update-article', 'delete-article'], $article)) {
  // the user cannot update or delete article
}

Gates generally give output as simple boolean values, but in some cases, we want to have more detailed responses like error messages, etc. For that we can use :

Illuminate\Auth\Access\Response from the gate:

<?php

use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;

Gate::define('edit-settings', function (User $user) {
    return $user->isAdmin
                ? Response::allow()
                : Response::deny('You must be an administrator.');
});

Policies

The policies are a way to logically organise authorization for a particular model or resource. 

So if we have an Articles on our website then we must have a :

App\Modeils|Article model 

and we can have an App\Policies\ArticlePolicy to authorize the user actions.

To generate a policy we can use the make: policy Artisan command, it will be created here app/Policies/ArticlePolicy.php:

php artisan make: policy ArticlePolicy

// the above will generate an empty policy class. 

php artisan make:policy ArticlePolicy –model=Article

// the above will generate a class with example policy methods related to viewing, creating, updating, and deleting the resource.

How to register policies in Laravel 8:

We need to register a policy once it is created, registering a policy is important to inform laravel which policy to use when authorising actions against the model.

We can register it using the Laravel service provider, see the example below:

<?php

namespace App\Providers;

use App\Models\Article;
use App\Policies\ArticlePolicy;
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 = [
        Article::class => ArticlePolicy::class,
    ];

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

        //
    }
}

Once we register our policies, we can write policies as below:

<?php

namespace App\Policies;
 
use App\User;
use App\Article;
use Illuminate\Auth\Access\HandlesAuthorization;
 
class PostPolicy
{
  use HandlesAuthorization;
 
  /**
   * Determine whether the user can view the article.
   *
   * @param  \App\User  $user
   * @param  \App\Article  $article
   * @return mixed
   */
  public function view(User $user, Article $article)
  {
    return TRUE;
  }
 
  /**
   * Determine whether the user can create articles.
   *
   * @param  \App\User  $user
   * @return mixed
   */
  public function create(User $user)
  {
    return $user->id > 0;
  }
 
  /**
   * Determine whether the user can update the article.
   *
   * @param  \App\User  $user
   * @param  \App\Article  $article
   * @return mixed
   */
  public function update(User $user, Article $article)
  {
    return $user->id == $article->user_id;
  }
 
  /**
   * Determine whether the user can delete the article.
   *
   * @param  \App\User  $user
   * @param  \App\Article  $article
   * @return mixed
   */
  public function delete(User $user, Article $article)
  {
    return $user->id == $article->user_id;
  }
}

The above example code had all the methods to authorize a user, let’s create some custom routes in our routes/wen.php file

<?php

Route::get('article/view', 'ArticleController@view');
Route::get('article/create', 'ArticleController@create');
Route::get('article/update', 'ArticleController@update');
Route::get('article/delete', 'ArticleController@delete');

For this here is a controller class:

app/Http/Controllers/PostController.php

<?php

namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Article;
use Illuminate\Support\Facades\Auth;
 
class ArticleController extends Controller
{
  public function view()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load article
    $article = Article::find(1);
     
    if ($user->can('view', $article)) {
      echo "Current logged in user is allowed to update the Article: {$article->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function create()
  {
    // get current logged in user
    $user = Auth::user();
 
    if ($user->can('create', Article::class)) {
      echo 'Current logged in user is allowed to create new articles.';
    } else {
      echo 'Not Authorized';
    }
 
    exit;
  }
 
  public function update()
  {
    // get current logged in user
    $user = Auth::user();
 
    // load article
    $article = Article::find(1);
 
    if ($user->can('update', $article)) {
      echo "Current logged in user is allowed to update the Article: {$article->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function delete()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load article
    $article = Article::find(1);
     
    if ($user->can('delete', $article)) {
      echo "Current logged in user is allowed to delete the Article: {$article->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
}

There are different ways we can authorize our actions using Policies. In our example above, we’ve used the User model to authorize our Article model actions.

Use User model offers two useful methods for authorization “can” and “cant”. The can method is used to check if the current user is able to execute actions and the cant is used to determine the inability to execute the action.

See the example below:

<?php

public function view()
{
  // get current logged in user
  $user = Auth::user();
   
  // load article
  $article = Article::find(1);
   
  if ($user->can('view', $article)) {
    echo "Current logged in user is allowed to update the Article: {$article->id}";
  } else {
    echo 'Not Authorized.';
  }
}

In the above example, we have the object of the user model, and we also had the object of the article model.

We have used the can method of the User model to authorize the view action of the Article model. The first argument of the can method is the action name that we want to authorize, and the second argument is the model object that we want to get authorized against.

We hope this tutorial will help you to learn the authorization of laravel gates and policies. Would you please comment or share this tutorial? In case you need help with Laravel applications, reach out to us. As a Laravel web development company, we can help you build highly intuitive and functional Laravel apps in no time. Contact us now for more details.

Author: Chandan Kumar

Tags: , , , ,

Recent Posts

Categories

Tags

Leave a Reply

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