Guide to Building “Simple ACL” in Laravel
Laravel’s authentication provides a simplified solution for registration, login, logout, and password reset, making it quicker and easier to implement for web applications.
However, if you need to control access to specific parts of a website, enable or disable certain sections for non-admin users, or ensure that a user can only edit their own contacts, you need to build an ACL (Access Control List) in Laravel (starting from version 5.1.11).
To build an ACL for your application, we use the built-in Gate class, which has been integrated into Laravel versions 5.1.11 and beyond. The Gate class allows you to check if a user (either the logged-in user or a specific user) is “allowed” to do something. Let’s look at the sample code below:
if (Gate::denies(‘update-contact’, $contact)) {
abort(403);
}
Place the code above in your controller and check whether the logged-in user is denied the update-contact permission, or you can use Gate::allows
to check the reverse.
Laravel’s ACL is built on the concept of “Ability“. An Ability is a key (e.g., update-contact).
DEFINING AN ABILITY FOR ACL
Define an “Ability” in the default position, the AuthServiceProvider.
class AuthServiceProvider extends ServiceProvider
{
public function boot(GateContract $gate)
{
parent::registerPolicies($gate);
$gate->define('update-contact', function ($user, $contact) {
return $user->id === $contact->user_id;
});
}
}
And check:
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
Another concept we should explore is Policies. Instead of writing too many definitions directly in the AuthServiceProvider, we can build a set of classes called Policies.
Run the command:
php artisan make:policy ContactPolicy
This will automatically generate the ContactPolicy file in the app/Policies folder with the default content.
id === $contact->user_id;
}
}
Now, register the class in the AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Contact::class => ContactPolicy::class,
];
}
Now we can place the following in the controller to check:
if (Gate::denies('update', $contact)) {
abort(403);
}