Add role and permission on your Laravel project 🔐

Nico Montiel - Apr 4 '23 - - Dev Community

Introduction

Authorization is a critical aspect of any application, as it ensures that users only have access to the resources they are allowed to see or modify. Laravel provides built-in features to make it easier to implement authorization in your application. In this post, we will learn how to implement authorization in Laravel without using any external libraries.

Why is Authorization important and how Laravel helps with that

Authorization is important for security reasons, as it ensures that users only have access to the parts of the application they are authorized to use. Laravel makes it easy to implement authorization through its built-in middleware, which can be used to protect routes and actions.

Creating the models

To keep this post from being too long, let's assume we've already created the migrations. If not, you can see the fillable property on the models and assume the table shape.
To implement authorization in Laravel without using external libraries, we need to create our own models for permissions, roles, and users. We can create the following models:

Permissions model

This model only contains the relationship with the roles. Here is a small description of the fields:

  • name: The permission name -> post.create
  • display_name: A formated name to show on your UI if is required -> Create Posts.
  • description: A brief description of the permission -> An User can create blog posts.
class Permission extends Model {
    protected $fillable = [
        'name',
        'display_name',
        'description',
    ];

    // Relationship with roles.
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

Role model

To create the relationship between the permissions and the roles, we need to create a pivot table called permission_role that has the permission_id and role_id fields.
Here we can see the relationship between the permissions and the users too.
The fields has the same meaning of the permissions table.

  • name: The role name -> reviewer
  • display_name: The formated name -> Post Reviewer
  • description: A brief description -> An User that can review a post and approve it.
class Role extends Model {
    protected $fillable = [
        'name',
        'display_name',
        'description',
    ];

    // Relationship with permissions
    public function permissions()
    {
        return $this->belongsToMany(Permission::class);
    }

    // Relationship with users
    public function users()
    {
        return $this->hasMany(User::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

User Model

Here we have the two escentials methods for our permissions system.

  • role(): Is our relationship with the Role model.
  • hasPermissionTo(): Here we receive as a parameter the permission name, and will return true if the user have the permissions, and false if don't have it.
class User extends Authenticatable {
    protected $fillable = [
        'first_name',
        'last_name',
        'role_id',
        'password',
    ];

    // Relationship with role
    public function role()
    {
        return $this->belongsTo(Role::class);
    }

    // Check if the user have the permission
    public function hasPermissionTo($permissionName)
    {
        return $this->role->permissions->contains('name', $permissionName);
    }
}
Enter fullscreen mode Exit fullscreen mode

Where implement this?

Great, so we have our authorization logic, but now what?
There are a few different ways you can implement this authorization logic in your Laravel application. Most you can use two different approaches for this:

Using Policies

class PostPolicy
{
    /**
     * Determine if an user can create a post.
     */
    public function update(User $user): bool
    {
        return $user->hasPermissionTo('post.create')
    }
}
Enter fullscreen mode Exit fullscreen mode

Read more: https://laravel.com/docs/10.x/authorization#creating-policies

Using a Middleware

class CreatePostMiddleware {
    public function handle(Request $request, Closure $next, $permission)
    {
        if (!auth()->user()->hasPermissionTo($permission)) {
            abort(403, 'Unauthorized action.');
        }

        return $next($request);
    }
}
Enter fullscreen mode Exit fullscreen mode

Read more: https://laravel.com/docs/10.x/middleware#defining-middleware

Summary

Implementing authorization without using external libraries is not difficult, and it gives you more control over how your application handles authorization. By creating your own models and relationships, and implementing the hasPermissionTo method, you can easily implement authorization in your Laravel application.

That's all, I hope it can be helpful for you 🥳

. . . . . . . .