How to Use Gates and Policy in Laravel? [SOLVED]


Laravel

Author: Steve Alila
Reviewer: Deepak Prasad

In this tutorial, we will explore the concepts of Gates and Policies in Laravel, two powerful features designed to simplify the process of implementing authorization and access control in your applications. Laravel provides a robust and flexible authorization system that allows you to manage user permissions and roles, ensuring that only authorized users can perform specific actions or access certain resources.

Gates in Laravel provide a mechanism for defining simple, reusable authorization checks, while Policies are designed for managing permissions on a more granular level, typically for resource-based actions. Both Gates and Policies work seamlessly with Laravel's built-in middleware and Eloquent ORM, enabling you to create complex authorization rules and apply them across your application with ease.

Throughout this tutorial, we will guide you through the process of creating and using Gates and Policies in Laravel, discuss their benefits, and demonstrate how to apply these features to real-world scenarios. We will cover the process of defining Gates and Policies, registering them in the application, and integrating them with routes and controllers.

By the end of this tutorial, you will have a solid understanding of how to use Gates and Policies in Laravel to implement efficient and secure authorization systems in your applications, ensuring a safer and more reliable user experience.

 

Understanding Gates and Policies for Efficient Authorization in Laravel

In Laravel, authorization plays a crucial role in ensuring the security and proper functioning of applications. Gates and Policies are two essential features that help manage authorization efficiently. Gates are defined in the app/providers/AuthServiceProvider.php file and decide whether a client can perform an action using the Gate facade.

use Illuminate\Support\Facades\Gate;

Gates are well-suited for controlling actions unrelated to specific resources or models. For instance, they can restrict access to the admin dashboard or prevent post deletion for users lacking the necessary permissions.

Policies, on the other hand, focus on organizing authorization logic around resources or models. You can create a policy using the php artisan make:policy <PolicyName> command. The resulting Policy class is located in the app/Policies/<PolicyName>.php file. Policies are ideal for authorizing actions related to resources or models, ensuring that only users with the right permissions can perform those actions.

 

Example - How to Use Laravel Gates

You can write a gate using the Gate facade's define method. The method takes two parameters:

Gate::define(<name>, <callback function>);

The name is an action that is authorizable for a given user. The callback function receives an instance of the User model as the first parameter and optional parameters and returns a boolean result. 

Here is an example.

<?php
...
    public function boot(): void
    {
        Gate::define('delete-blog', function (User $user, Blog $blog) {
            return $user->id === $blog->user_id;
        });
    }
...

We create a delete-blog action in the boot() method of the app/providers/AuthServiceProvider.php file. The callback function that receives User and Blog model instances determines the action. In the above case, user can only delete a blog if their id equals the id on the blog. 

We could also create the action from a policy class. 

Gate::define('delete-blog', [BlogPolicy::class, 'delete']);

The above statement means the logic of deleting the user lies in the delete method of the BlogPolicy policy's class.

After creating a gate, you can use it to authorize actions using the Gate facade's allows or denies methods.

<?php
...
use Illuminate\Support\Facades\Gate;
 
class BlogController extends Controller
{
    public function destroy(Request $request, Blog $blog)
    {
        if (! Gate::allows('delete-blog', $blog)) { 
          abort(403); 
        }
    }
}

We forbid the user from deleting a blog if they are not ! authorized. As the name suggests, the allows method grants permission. 

use gates and policy in Laravel

We could also achieve the above code's effect by excluding the not ! operator and replacing the allows with the denies method.

Gate::denies('delete-blog', $blog)

Apart from explicitly telling Laravel to end the request with 403, you can let Laravel to attempt to authorize the action or send an AuthorizationException exception. You can do that using the authorize method.

Gate::authorize('delete-blog', $blog)

An instance of the AuthorizationException exception will be converted to the 403 HTTP response. Besides, you can authorize multiple actions using any or none methods.

// any
Gate::any(['delete-blog', 'update-blog'], $blog)
// none
Gate::none(['delete-blog', 'update-blog'], $blog)

You probably wonder why we did not passed the user object during the authorization in the above methods. That is because Laravel passes the authenticated user to the closure. However, you can change the default behavior by passing another user other than the authenticated one using the forUser method.

Gate::forUser($user)->allows('delete-blog', $blog)

The allows method returns a single boolean value even when the gate returns an authorization response. However, you can use the inspect method to get the full authorization response.

$response = Gate::inspect('delete-users');
 
if ($response->allowed()) {
    // action authorized
}

Lastly, you may intersect gate checks using before or after methods. The before method precedes all authorization checks, while the after method runs after all other authorization checks. 

Here is an example.

Gate::before(function (User $user, string $ability) {
    if ($user->isAdministrator()) {
        return true;
    }
});

The before method grants all abilities to the specified user. 

 

Example - How to use Laravel Policies

A policy is often tied to a model. For example, a BlogPolicy wraps around a Blog model to control who can create, read, update, or delete a resource. Each controller method, which mostly has the same name as the policy method, maps to the policy method.

Controller Method Policy Method
index viewAny
show view
create create
store create
edit update
update update
destroy delete

Each policy method is referred to as an ability. Each ability returns a boolean value.

Like models, policies are created with the artisan command. You can create an empty policy,

php artisan make:policy BlogPolicy

or one with methods for performing actions on to the target model.

php artisan make:policy BlogPolicy --model=Blog

After that, you need to inform Laravel to use the policy when authorizing actions. You do that by registering the policy in the App\Providers\AuthServiceProvider.php file's policies property.

<?php
...
use App\Models\Blog;
use App\Policies\BlogPolicy;
 
class AuthServiceProvider extends ServiceProvider
{
...
    protected $policies = [
        Blog::class => BlogPolicy::class,
    ];
 ...
}

How to Use Gates and Policy in Laravel? [SOLVED]

Now you can add authorization methods. For example, you can check if the user can delete the specified blog.

<?php
 
namespace App\Policies;
 
use App\Models\Blog;
use App\Models\User;
 
class PostPolicy
{
    public function delete(User $user, Blog $blog): bool
    {
        return $user->id === $blog->user_id;
    }
}

The delete method checks if the given user created the blog before letting the user delete it. You can combine the policy with a method from the Response class to return a detailed response. 

// in app/Policies/BlogPolicy.php
... 
public function delete(User $user, Blog $blog): Response
{
    return $user->id === $blog->user_id
                ? Response::allow()
                : Response::deny('You can only delete your post');
}

The delete method checks if the blog's user_id column matches the corresponding foreign key on the users table. It authorizes the delete action using the Response class' allow() method. Otherwise, it returns a detailed message with the reason for denying the action. You can replace the deny() with denyWithStatus(404) or denyAsNotFound() methods to hide a resource via 404 HTTP response. 

return $user->id === $blog->user_id ? Response::allow() : Response::denyAsNotFound();

Besides, you can create a policy from a user instance only. For example, you may only allow users to create posts if they have a writer role

public function create(User $user): bool
{
    return $user->role == 'writer';
}

You can authorize resources with policies via the User model, Controller helpers, or Blade templates. For instance, the User model has can and cannot methods that receive the intended action and model before authorizing a resource.

// in app/Http/Controllers/BlogController.php
<?php
...
    public function destroy(Request $request, Blog $blog)
    {
        if ($request->user()->cannot('delete', $blog)) {
            abort(403);
        }
        // delete the post
    }
...

Similarly, you can use Blade templates to determine the viewable resource using the policies with @can or @cannot derivatives.

@can('delete', $blog)
    <button><a href="{{ route('/destroy', $blog) }}">Delete</a></button>
@endcan

Laravel checks if the authenticated user can delete a blog before showing them the delete button.

How to Use Gates and Policy in Laravel? [SOLVED]

 

Summary

In this tutorial, we discussed the concepts of Gates and Policies in Laravel, which are crucial for implementing efficient and secure authorization systems in applications. Authorization plays a vital role in determining whether a client is allowed to access or use specific resources or perform certain actions. Gates and Policies in Laravel offer a robust and flexible way to manage authorization and access control.

Gates are used for defining simple, reusable authorization checks that are not tied to specific resources or models. They are defined in the app/providers/AuthServiceProvider.php file and use the Gate facade. Gates are ideal for controlling actions such as restricting access to an admin dashboard or preventing post deletion based on user permissions.

Policies, in contrast, focus on organizing authorization logic around resources or models. They are created using the php artisan make:policy <PolicyName> command, resulting in a Policy class located in the app/Policies/<PolicyName>.php file. Policies are primarily used for authorizing actions related to resources or models, ensuring that only users with the right permissions can perform those actions.

By understanding how to use Gates and Policies in Laravel, developers can build complex and efficient authorization systems that ensure the security and proper functioning of their applications. These features provide a powerful and flexible approach to managing authorization, ultimately leading to a safer and more reliable user experience.

 

Further Reading

Laravel Authorization

 

Steve Alila

Steve Alila

He specializes in web design, WordPress development, and data analysis, with proficiency in Python, JavaScript, and data extraction tools. Additionally, he excels in web API development, AI integration, and data presentation using Matplotlib and Plotly. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment