One of the most common features in any web application is authentication, which allows a user to log in or log out of an application to securely manage their information. However, many a time an application might also want to restrict access to certain aspects of the system to a certain type of users. This second level of screening is known as Access Control. I recently had to implement a very advanced and granular level of access control in a Laravel API based Application. So let me show you how you can implement access control using permissions and roles in a Vue SPA with a Laravel 7 back-end.
This tutorial is the first of the two-part series that will cover this entire topic in detail.
Vue SPA – Laravel 7 Access Control Overview
We will build a Laravel 7 API based application with a standalone Vue SPA front-end. The app has three types of roles, namely, Super Admin, User Manager, and Role Manager. These roles, in turn, grant the User a set of permissions. To clarify, each permission is mapped to one action. For example, View Users, Edit users, etc. Therefore, based upon the User’s permission, the front-end dashboard is dynamically populated. Likewise, the same check is present on the back-end as well so that the user only has access to the APIs that they have permissions to access.

Laravel API Application Setup
If you have already installed and set up your Laravel application, including a database, and also set up authentication, then you can skip to the “Composer Package Setup” section.
Create a new Laravel Application
We will start by updating our composer and pulling in the Laravel installer. After that, we will create a new Laravel 7 Application.
composer update
composer global require laravel/installer
laravel new laravel-api-role-permissions
cd laravel new laravel-api-role-permissions
Generate new application key using Artisan
The application key is used to secure User sessions and cookies in Laravel. This command generates a key and sets it as APP_KEY
in your .env
file. Subsequently, if you want to learn more about what this key is used for, check this helpful article.
php artisan key:generate
Set up a database for your application
Here, I have created a MySQL database named laravel_api
and set the connection details in my .env
file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=root
DB_PASSWORD=
Make sure to set your database credentials accordingly.
Install Laravel’s UI package and generate authentication scaffolding
We will need this package in order to start using Laravel’s default authentication module. So let’s pull that into our application.
composer require laravel/ui
After that, let’s generate the authentication views and scaffolding.
php artisan ui vue --auth
npm install && npm run dev
Composer Package Setup
We will make use of an excellent package called
laravel-permissions to implement a granular, permission-based access control in our application.
Install laravel-permissions
package using Composer
This command will pull in the latest version of this package from Packagist:
composer require spatie/laravel-permission
Register the package’s service provider
This will make sure the package’s functionality is bootstrapped along with our Laravel application. Additionally, you can learn more about service providers in Laravel documentation.
'providers' => [
// ...
Spatie\Permission\PermissionServiceProvider::class,
];
Publish the package’s migrations and configuration file
This package comes with migrations that create tables such as roles and permissions. In addition, a permission.php
file is also pushed to the config
directory.
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Run your migrations
Finally, we complete the setup by running our migrations. After this, our authentication and roles/permission related tables will be created in the database.
php artisan migrate
Prepare User Model for Access Control
We will start by adding Spatie\Permission\Traits\HasRoles
trait to our User model in User.php
.
...
class User extends Authenticatable
{
use Notifiable, HasRoles;
..
After that, your User model should now be associated with the laravel-permissions
package. To clarify, this establishes relationships such as Roles and Permissions to the User model.
Create Permissions and Roles
Now is the time to decide what kind of permissions and roles our application will have. Further, to show you guys a good example, I will set up the following set of permissions and roles.
Permissions
-
View All Users: A permission that enables access to
/api/users
API. The authenticated user will be able to view all users registered in the system. -
Edit All Users: A permission that enables access to
/api/user/{id}/edit
API. Subsequently, the user will be able to edit all users registered in the system. - Assign Role: A permission that will enable access to assign one or more roles to a User in the system.
- Unassign Role: A permission that will enable access to remove one or more roles assigned to a User in the system.
-
View All Permissions: A permission that enables access to the
/api/permissions
API. -
View All Roles: A permission that enables access to the
/api/roles
API.
Roles
- Super Admin: This role will have all the permissions listed above.
-
User Manager: This role will have
View All Users
andEdit All Users
permissions. - Role Manager: This role will responsible for assigning and unassigning roles to a user.
Create artisan command
We will create an artisan command which will generate the permissions and roles listed above. This command should be run just once during the initial setup of your application. After that, we will also assign permissions to these commands.
php artisan make:command RolePermissionBootstrap
Add the following logic to app/Console/Commands/RolePermissionBootstrap.php
that creates permissions and roles mentioned above. Subsequently, we assign proper permissions to each role.
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolePermissionBootstrap extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'laravel_api:bootstrap';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create roles and permissions';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$roles = ["Super Admin", "User Manager","Role Manager"];
$permissions = [
"View All Users",
"Edit All Users",
"Assign Role",
"Unassign Role",
"View All Permissions",
"View All Roles"];
$this->line('------------- Setting Up Roles:');
foreach ($roles as $role) {
$role = Role::updateOrCreate(['name' => $role, 'guard_name' => 'api']);
$this->info("Created " . $role->name . " Role");
}
$this->line('------------- Setting Up Permissions:');
$superAdminRole = Role::where('name', "Super Admin")->first();
foreach ($permissions as $perm_name) {
$permission = Permission::updateOrCreate(['name' => $perm_name,
'guard_name' => 'api']);
$superAdminRole->givePermissionTo($permission);
$this->info("Created " . $permission->name . " Permission");
}
$this->info("All permissions are granted to Super Admin");
$this->line('------------- Application Bootstrapping is Complete: \n');
}
}
Run the Artisan command
Run laravel_api:bootstrap
to generate roles and permissions and persist them into the database.
php artisan laravel_api:bootstrap
The output looks something like this:

Define APIs for Access Control
Now that we have our roles and permissions in place, let’s define our base APIs in routes/api.php
to assign or remove any role from a user. However, for the sake of brevity, I will be implementing only the assign/unassigning of a role here as the view/edit user logic will be specific to your application.
Note: If you still want to see my User view/edit logic, then I will be attaching a link to one of my projects at the end of this tutorial series. However, that project demonstrates access control at a more complex level than the scenario covered here. Therefore, you should read through this entire tutorial before you can make sense of that project.
<?php
Route::post('register', 'AuthController@register')
->name('register');
Route::post('login', 'AuthController@login')
->name('login');
Route::group([
'middleware' => 'auth:api'
], function () {
Route::get('logout', 'AuthController@logout')->name('logout');
Route::get('/permissions', 'RoleManager@permissionsIndex')
->name('permissions.index')
->middleware('permission:View All Permissions');
Route::get('/roles', 'RoleManager@rolesIndex')
->name('roles.index')
->middleware('permission:View All Roles');
Route::post('/roles/{role}/assign/{user}', 'RoleManager@rolesAddUser')
->name('roles.addUser')
->middleware('permission:Assign Role');
Route::post('/roles/{role}/unassign/{user}', 'RoleManager@rolesRemoveUser')
->name('roles.removeUser')
->middleware('permission:Unassign Role');
});
As you can see above, I’m using the permission:
middleware to control who can access those APIs. So only those with appropriate permissions will be able to invoke the API without getting a 405, Not Allowed HTTP response.
Create RoleManager
Controller
php artisan make:controller RoleManager --api
Now let’s define the logic for assigning a role to a user and un-assigning it. To clarify, we mainly use the assignRole()
and removeRole()
methods provided by the laravel-permissions
package.
class RoleManager extends Controller
{
public function permissionsIndex()
{
return Permission::all()->paginate(100);
}
public function rolesIndex()
{
return Role::all()->paginate(100);
}
public function rolesAddUser(Request $request, Role $role, User $user)
{
$user->assignRole($role);
return response()->json([
"message" => $role->name . " Role successfully assigned to User!"
], 200);
}
public function rolesRemoveUser(Request $request, Role $role, User $user)
{
$user->removeRole($role);
return response()->json([
"message" => $role->name . " Role successfully removed from User"
], 200);
}
}
That’s it! Our Laravel API is ready. And we have come halfway in implementing access control using permissions and roles in a Vue SPA with a Laravel 7 back-end.
In the next part of this tutorial, we will see how to integrate these APIs into a standalone Vue Single Page Application.
Comments