Securing Laravel APIs with Tyro: A Comprehensive Role and Privilege Guide
Overview
Prerequisites
To follow this guide, you should have a baseline understanding of the

Key Libraries & Tools
- Tyro: The primary authorization engine handling roles and privileges.
- Laravel Sanctum: The underlying dependency used for generating and verifying API tokens.
- Postman: An API client used to test login endpoints and protected routes.
- VS Code: The recommended code editor for managing your project files.
Code Walkthrough
1. Installation and Scaffolding
Begin by pulling the package into a fresh project and running the installation command. This process automatically sets up the necessary API infrastructure.
composer require hasinhayder/tyro
php artisan tyro:install
2. Model Configuration
Integrate the User model by adding the HasTyroRoles trait. This enables the model to interact with the underlying role-user pivot tables.
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use HasinHayder\Tyro\Traits\HasTyroRoles;
class User extends Authenticatable
{
use HasTyroRoles;
}
3. Protecting Routes with Privileges
Unlike standard Sanctum protection, api.php routes file, apply the privilege middleware to sensitive endpoints.
Route::middleware(['auth:sanctum', 'privilege:posts.create'])->group(function () {
Route::post('/posts', [PostController::class, 'store']);
});
Syntax Notes
user_roles rather than the traditional alphabetical role_user format. It also utilizes a "Privilege" nomenclature which is functionally equivalent to "Permissions" in other ecosystems but allows for more granular slug-based checks.
Practical Examples
In a real-world scenario, you might have an Admin role with a posts.create privilege. When an Admin logs in via /api/login, they receive a token. Sending a POST request to /api/posts with this token succeeds. However, a regular user with a valid token but lacking the specific posts.create privilege will receive a 403 Forbidden response, ensuring tight security for your data-writing endpoints.
Tips & Gotchas
When testing with Accept: application/json. Without this, php artisan db:seed --class=TyroSeeder during initial setup to populate the default admin accounts.