Laravel Authorization: Using Gates and Policies

This guide explains Laravel's built‑in authorization features, covering how to define and register Gates and Policies, how to check permissions via the Gate facade, middleware, controller helpers, Blade directives, and includes practical code examples for common CRUD actions.

Laravel Tech Community
Laravel Tech Community
Laravel Tech Community
Laravel Authorization: Using Gates and Policies

Introduction

Laravel provides a simple way to handle user authorization in addition to its out‑of‑the‑box authentication services, offering two main mechanisms: Gates and Policies.

Gates are comparable to routes, providing a closure‑based approach, while Policies are similar to controllers, grouping authorization logic around a specific model or resource.

Most applications use both Gates and Policies together; Gates are ideal for actions unrelated to a specific model (e.g., admin panel access), whereas Policies are suited for model‑specific checks.

Gates

Defining Gates

Gates are defined in App\Providers\AuthServiceProvider using the Gate facade. They receive a user instance as the first argument and may accept additional parameters such as an Eloquent model.

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

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

Gates can also be defined using a controller‑style callback string:

Gate::define('update-post', 'PostPolicy@update');

Resource Gates

The resource method can define multiple related gates at once: Gate::resource('posts', 'PostPolicy'); This is equivalent to defining individual gates such as posts.view, posts.create, posts.update, and posts.delete. Additional custom actions can be added by passing an array as the third argument:

Gate::resource('posts', 'PostPolicy', [
    'image' => 'updateImage',
    'photo' => 'updatePhoto',
]);

Authorizing Actions with Gates

Use Gate::allows or Gate::denies to check permissions. The currently authenticated user is automatically passed to the gate closure.

if (Gate::allows('update-post', $post)) {
    // The user may update the post...
}

if (Gate::denies('update-post', $post)) {
    // The user may not update the post...
}

To check a specific user, use Gate::forUser($user)->allows(...) or ->denies(...).

if (Gate::forUser($user)->allows('update-post', $post)) {
    // User can update...
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // User cannot update...
}

Creating Policies

Generating a Policy

Run php artisan make:policy PostPolicy to generate an empty policy class in app/Policies. Use the --model=Post option to scaffold basic CRUD methods.

php artisan make:policy PostPolicy --model=Post
{tip} All policy methods are resolved via Laravel's service container, allowing automatic dependency injection.

Registering Policies

Add model‑policy mappings to the policies property of App\Providers\AuthServiceProvider and call $this->registerPolicies() in the boot method.

<?php

namespace App\Providers;

use App\Post;
use App\Policies\PostPolicy;
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 = [
        Post::class => PostPolicy::class,
    ];

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

Writing Policy Methods

A typical update method receives a User and a Post and returns a boolean indicating ownership.

<?php

namespace App\Policies;

use App\User;
use App\Post;

class PostPolicy
{
    /**
     * Determine if the given user can update the post.
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Additional methods such as view, delete, or custom actions can be added similarly. For actions that do not require a model instance (e.g., create), define the method with only the User parameter.

public function create(User $user)
{
    // Determine if the user may create a post...
}

Policy Filters

A before method runs before any other policy method, allowing you to grant or deny all abilities for a given user (commonly used for super‑admin checks).

public function before($user, $ability)
{
    if ($user->isSuperAdmin()) {
        return true;
    }
}

Authorizing Actions

Using the User Model

The User model provides can and cant methods. Example:

if ($user->can('update', $post)) {
    // Authorized
}

If a policy is registered for the model, can will invoke it; otherwise it falls back to a Gate with the same name.

Actions Without a Model

For actions like create, pass the class name instead of an instance:

if ($user->can('create', Post::class)) {
    // Authorized to create a post
}

Using Middleware

The Illuminate\Auth\Middleware\Authorize middleware can protect routes. Example:

Route::put('/post/{post}', function (Post $post) {
    // Update logic
})->middleware('can:update,post');

For model‑less actions, pass the class name:

Route::post('/post', function () {
    // Create logic
})->middleware('can:create,App\Post');

Controller Helper Method

Controllers extending App\Http\Controllers\Controller can call $this->authorize('update', $post). If the check fails, an AuthorizationException (HTTP 403) is thrown.

<?php

namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);
        // Update logic...
    }
}

Model‑less Actions

Pass the class name to authorize for actions like create:

public function create(Request $request)
{
    $this->authorize('create', Post::class);
    // Creation logic...
}

Blade Directives

Use @can / @cannot (or @elsecan / @elsecannot) to conditionally display content based on permissions.

@can('update', $post)
    <!-- User can update -->
@elsecan('create', App\Post::class)
    <!-- User can create -->
@endcan

@cannot('update', $post)
    <!-- User cannot update -->
@endcannot

These directives are shorthand for the equivalent @if (Auth::user()->can(...)) checks.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PHPAuthorizationLaravelgatesPolicies
Laravel Tech Community
Written by

Laravel Tech Community

Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.