Laravel Policies – Controlling Authorization in Laravel
Laravel Policies are a great way to protect actions on your Eloquent Model. Laravel Policies are the part of Laravel Authorization that helps you to protect resources from unauthorized access.
In this post, I will show you how you can create a Laravel Policy to protect actions on your model. You might be familiar with Laravel Policies, this post is intended to help new users of Laravel.
What is Laravel Policy?
Laravel Policy is a class, where you can organize the authorization logic of your application. For example, you might have a blog application built in Laravel and want to protect that only users who own the blog post can delete it. In this post, I will show you how you can achieve this.
Basic Setup
For this post, I assume you have a Laravel application set up. Firstly you need to update database credentials, in .env
file like below.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=blog DB_USERNAME=root DB_PASSWORD=
Next we have to create model, migration and controller for users and posts. Laravel installtion comes with User
model and migration so we will create only Post
model and migration.
Run below command in terminal to generate, model and migration for Post.
php artisan make:model Post -m
Open you post’s migration file and add below:
Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('content'); $table->boolen('status'); $table->integer('user_id'); $table->timestamps(); });
Once you have your migration ready, run php artisan migrate
to create users and posts table in the database.
If everything works fine for you, you will able to see two tables in your database called users
and posts
. Now create some users and posts in database tables. You can make a seed or add them manually.
Create Policy
Laravel provides an artisan command to generate a policy. Run below command to generate a policy which will be created in the folder app/Policies
.
php artisan make:policy PostPolicy
Note
It’s always recommended to create policy prefix with the model name. In out case it was Post model, so we created PostPolicy.
If you want to generate all CRUD methods within the policy you can run below command.
php artisan make:policy PostPolicy --model=Post
The first command will create below class.
namespace App\Policies; use App\User; use Illuminate\Auth\Access\HandlesAuthorization; class PostPolicy { use HandlesAuthorization; /** * Create a new policy instance. * * @return void */ public function __construct() { // } }
Adding Logic to Policy
Now we have generated our policy, its time to add our logic to this policy. We want to allow delete method only to users who have created a post. For example, if we have a user with id
3, and our one of post belong to this user by using user_id
column, we want to allow to delete this post by the only user with id 3.
We will create a new method called delete()
as we want to restrict delete action, like below.
public function delete(User $user, Post $post) { return $user->id === $post->user_id; }
This method will check whether the post creator is this user or not and return true or false.
Registering Policy
Once we have updated our policy logic, it’s time to register this policy. Open AuthServicProvider file from app/Providers
.
Add your PostPolicy to the $policies
array like below.
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 = [ 'App\Model' => 'App\Policies\ModelPolicy', Post::class => PostPolicy::class, ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); // } }
Using Policy in Views
Once you have followed all the above steps, now you can use this policy in the views. You can use the @can
and @cannot
blade directive to check the policy.
For example,
@can('delete', $post) // show post delete button @endcan
@cannot('delete', $post) // disable post delete button @endcannot
It’s up to you which directive you want to use depending on your application.
Using Policy in Model
You can also use the policy in your Post
model. You can use the below code to check if the Post is deletable for the current user in any of model’s method.
if ($user->can('delete', $post)) { // add your actions here }
Using Policy in Controller
Now we will use the same policy in our PostController to authorize the delete functionality like so:
public function delete(Post $post) { $this->authorize('delete', $post); // The current user can delete the post }
Laravel policies provide extra control on the authorization. You can use the polices to create a full fledge permissions management system which will make your whole application controllable and add extra security to your application.
If you have any question or suggestion, please leave them in the comments box below.