Laravel 12 • PHP 8.2+ • Sanctum 4.0

The Powerful
Auth, Roles & Privileges for Laravel 12

Complete Authentication, Authorization, and Role & Privilege Management. 40+ CLI commands, 7 Blade directives, middleware, and optional REST API. Your Swiss Army knife for Laravel security.

composer require hasinhayder/tyro
40+
CLI Commands
7
Blade Directives
API + Web
Works Everywhere

Why Choose Tyro

The complete auth & access control toolkit for Laravel applications.

Complete Auth System

Full authentication with Sanctum, role-based access control, fine-grained privileges, and Laravel Gate integration out of the box.

Security Hardened

Sanctum tokens mirror role + privilege slugs, suspension workflows revoke tokens instantly, battle-tested middleware stack.

Roles & Privileges

Manage reusable privileges per role via HTTP or CLI, then reuse them in middleware or $user->can() calls.

40+ CLI Commands

Manage users, roles, privileges, and tokens from the terminal. Perfect for automation, CI/CD, and incident response.

7 Blade Directives

Use @usercan, @hasrole, @hasanyrole, @hasroles, @hasprivilege, @hasanyprivilege, @hasprivileges in your views. Clean, readable templates.

Optional REST API

Need API endpoints? They're included. Don't need them? Disable with one config flag. Tyro adapts to your needs.

Get Started in 2 Steps

From zero to production-ready API in under 60 seconds

1

Install the Package

composer require hasinhayder/tyro
2

Run the Installer

php artisan tyro:install

Wraps install:api + migrate + seed + prepare-user-model

That's it! You now have complete authentication, authorization, roles, privileges, 7 Blade directives, middleware, and 40+ CLI commands.

Read Full Documentation

Powerful Role & Privilege System

Check permissions anywhere in your application with a clean, Laravel-style API

  • Gate integration with $user->can()
  • Real-time privilege checking
  • User suspension with token revocation
  • Performance optimized
app/Http/Controllers/ReportController.php
if ($request->user()->can('reports.run')) {
    // User has the privilege through their roles
}

if ($request->user()->hasRole('admin')) {
    // Check specific role
}

if ($request->user()->hasPrivileges(['billing.view', 'reports.run'])) {
    // Require multiple privileges
}

// Suspend a user and revoke all tokens
$user->suspend('Policy violation');

// Check suspension status
if ($user->isSuspended()) {
    return response()->json([
        'error' => $user->getSuspensionReason()
    ], 423);
}

User Suspension Workflows

Freeze accounts instantly, revoke tokens, and manage suspensions with a clean API

  • Instant account suspension with optional reason
  • Automatic Sanctum token revocation
  • CLI commands for suspension management
  • REST API endpoints for automation
app/Http/Controllers/AdminController.php
// Suspend a user with reason
$user->suspend('Policy violation');

// All tokens are automatically revoked
// User cannot access protected routes

// Check suspension status
if ($user->isSuspended()) {
    $reason = $user->getSuspensionReason();
    return response()->json([
        'error' => 'Account suspended',
        'reason' => $reason
    ], 423);
}

// Unsuspend when ready
$user->unsuspend();

// CLI: php artisan tyro:suspend-user --user=1
// CLI: php artisan tyro:unsuspend-user --user=1

Protecting Routes with Middleware

Use powerful middleware to protect your routes based on roles, privileges, and abilities

Role-Based Protection

Restrict routes to users with specific roles using role: for a single role or roles: for multiple roles.

  • role:admin - Require single role
  • roles:admin,editor - Require any of multiple roles
  • Returns 403 Forbidden for unauthorized access
routes/api.php
use Illuminate\Support\Facades\Route;

// Single role protection
Route::middleware(['auth:sanctum', 'role:admin'])->group(function () {
    Route::get('/admin/dashboard', [AdminController::class, 'dashboard']);
    Route::get('/admin/settings', [AdminController::class, 'settings']);
});

// Multiple roles - user needs ANY of these roles
Route::middleware(['auth:sanctum', 'roles:admin,editor,moderator'])->group(function () {
    Route::get('/manage/posts', [PostController::class, 'index']);
    Route::post('/manage/posts', [PostController::class, 'store']);
});

// Single route with role middleware
Route::get('/super-admin/logs', [LogController::class, 'index'])
    ->middleware(['auth:sanctum', 'role:super-admin']);

Privilege-Based Protection

Protect routes based on specific privileges using privilege: for a single privilege or privileges: for multiple privileges.

  • privilege:reports.view - Require single privilege
  • privileges:billing.view,invoices.create - Require any privilege
  • Fine-grained access control beyond roles
routes/api.php
use Illuminate\Support\Facades\Route;

// Single privilege protection
Route::middleware(['auth:sanctum', 'privilege:reports.view'])->group(function () {
    Route::get('/reports', [ReportController::class, 'index']);
    Route::get('/reports/{id}', [ReportController::class, 'show']);
});

// Multiple privileges - user needs ANY of these privileges
Route::middleware(['auth:sanctum', 'privileges:billing.view,billing.edit'])->group(function () {
    Route::get('/billing', [BillingController::class, 'index']);
    Route::put('/billing/{id}', [BillingController::class, 'update']);
});

// Protect sensitive operations
Route::delete('/users/{id}', [UserController::class, 'destroy'])
    ->middleware(['auth:sanctum', 'privilege:users.delete']);

Ability-Based Protection

Use Laravel Sanctum's built-in ability: and abilities: middleware for token-based ability checks.

  • ability:admin - Check single token ability
  • abilities:posts.create,posts.edit - Require ALL abilities
  • Tyro tokens include role + privilege slugs as abilities
routes/api.php
use Illuminate\Support\Facades\Route;

// Single ability check (role or privilege slug)
Route::middleware(['auth:sanctum', 'ability:admin'])->group(function () {
    Route::get('/admin/stats', [StatsController::class, 'index']);
});

// Multiple abilities - user token must have ALL specified abilities
Route::middleware(['auth:sanctum', 'abilities:posts.create,posts.publish'])->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
    Route::post('/posts/{id}/publish', [PostController::class, 'publish']);
});

// Combine with other middleware
Route::middleware([
    'auth:sanctum',
    'ability:reports.run',
    'throttle:60,1'
])->get('/reports/generate', [ReportController::class, 'generate']);

Tip: When using Tyro, Sanctum tokens automatically include all role slugs and privilege slugs as abilities. This means ability:admin works just like role:admin for API token authentication.

7 Blade Directives

Conditionally render content based on user permissions with clean, readable syntax

@usercan directive
{{-- Check if user can perform action via can() --}}
@usercan('admin')
    <div class="admin-panel">
        <h2>Admin Dashboard</h2>
        <p>Welcome to the admin area!</p>
    </div>
@endusercan

@usercan('edit-posts')
    <button class="btn btn-primary">
        Edit Post
    </button>
@endusercan

Uses the can() method to check if user has a role or privilege. Works with both role slugs and privilege slugs.

@hasrole directive
{{-- Check if user has a specific role --}}
@hasrole('admin')
    <p>Welcome, Admin!</p>
    <a href="/admin/settings">Settings</a>
@endhasrole

@hasrole('editor')
    <a href="/dashboard/editor" class="nav-link">
        Editor Dashboard
    </a>
@endhasrole

@hasrole('super-admin')
    <button class="btn-danger">
        Critical Actions
    </button>
@endhasrole

Checks if the authenticated user has a specific role by its slug. Returns false if not authenticated.

@hasanyrole directive
{{-- Check if user has ANY of the roles --}}
@hasanyrole('admin', 'editor', 'moderator')
    <div class="management-tools">
        <h3>Management Tools</h3>
        <p>You have access to management features</p>
        <a href="/manage">Open Dashboard</a>
    </div>
@endhasanyrole

@hasanyrole('author', 'contributor')
    <div class="content-section">
        <button>Create New Post</button>
    </div>
@endhasanyrole

Renders content if the user has at least one of the specified roles. Great for showing shared features across multiple roles.

@hasroles directive
{{-- Require ALL specified roles --}}
@hasroles('admin', 'super-admin')
    <div class="super-admin-panel">
        <h2>Super Admin Controls</h2>
        <p>You have both admin and super-admin roles</p>
        <button class="btn-danger">
            System Configuration
        </button>
        <button class="btn-warning">
            Delete All Data
        </button>
    </div>
@endhasroles

Renders content only if the user has ALL of the specified roles. Use for features requiring multiple role assignments.

@hasprivilege directive
{{-- Check for a specific privilege --}}
@hasprivilege('delete-users')
    <button class="btn btn-danger" onclick="deleteUser()">
        Delete User
    </button>
@endhasprivilege

@hasprivilege('view-reports')
    <a href="/reports" class="nav-link">
        <i class="icon-reports"></i> View Reports
    </a>
@endhasprivilege

@hasprivilege('manage-settings')
    <a href="/settings">System Settings</a>
@endhasprivilege

Checks if the user has a specific privilege through any of their assigned roles. More granular than role checks.

@hasanyprivilege directive
{{-- Check for ANY of the privileges --}}
@hasanyprivilege('edit-posts', 'delete-posts', 'publish-posts')
    <div class="post-actions">
        <h4>Post Management</h4>
        @hasprivilege('edit-posts')
            <button>Edit</button>
        @endhasprivilege
        @hasprivilege('delete-posts')
            <button>Delete</button>
        @endhasprivilege
        @hasprivilege('publish-posts')
            <button>Publish</button>
        @endhasprivilege
    </div>
@endhasanyprivilege

Shows content if user has at least one of the listed privileges. Perfect for showing action panels with conditional buttons.

@hasprivileges directive
{{-- Require ALL specified privileges --}}
@hasprivileges('create-invoices', 'approve-invoices')
    <button class="btn btn-success">
        Create and Approve Invoice
    </button>
@endhasprivileges

@hasprivileges('view-reports', 'export-reports')
    <div class="reports-section">
        <a href="/reports">View Reports</a>
        <button onclick="exportReport()">
            Export to PDF
        </button>
    </div>
@endhasprivileges

Renders content only if the user has ALL specified privileges. Use for actions requiring multiple permissions.

All directives automatically return false when no user is authenticated. They're registered automatically when Tyro is loaded.

Powerful CLI Commands

40+ Artisan commands for complete Role and Privilege management and inspection without touching the database or writing raw SQL

tyro:install

Run Laravel's install:api, migrate, and optionally seed or prepare user model

tyro:prepare-user-model

Automatically add HasApiTokens and HasTyroRoles to your User model

tyro:seed

Run the full TyroSeeder (roles + bootstrap admin)

tyro:publish-config

Drop config/tyro.php into your app

tyro:publish-migrations

Copy Tyro's migrations into your database/migrations directory

tyro:create-user

Prompt for name/email/password and attach the default role

tyro:users

Inspect users with their role slugs and suspension status

tyro:users-with-roles

Display users with their role slugs and suspension column

tyro:suspend-user

Suspend a user with optional reason or lift with --unsuspend

tyro:unsuspend-user

Dedicated shortcut to lift user suspensions

tyro:suspended-users

Show every suspended user, when locked, and why

tyro:update-user

Update user details while ensuring you don't remove the last admin

tyro:delete-user

Delete a user while ensuring you don't remove the last admin

tyro:user-privileges

Display the real-time privilege table a user inherits through their roles

tyro:roles

Display all roles with user counts

tyro:roles-with-privileges

Display roles alongside their attached privilege slugs and user counts

tyro:create-role

Manage custom roles (protected slugs cannot be renamed or deleted)

tyro:update-role

Update existing role details

tyro:delete-role

Delete a role (protected slugs cannot be deleted)

tyro:assign-role

Attach a role to a user by email/ID

tyro:delete-user-role

Detach a role from a user

tyro:role-users

List all users currently attached to a given role

tyro:user-roles

Display a specific user's roles and attached privileges

tyro:seed-roles

Reapply the default role catalogue

tyro:flush-roles

Truncate the roles + pivot tables without re-seeding

tyro:privileges

List every privilege and which roles currently own it

tyro:add-privilege

Create new privilege records

tyro:update-privilege

Edit existing privilege records

tyro:delete-privilege

Remove privilege records

tyro:attach-privilege

Attach privileges to roles via slug or ID

tyro:detach-privilege

Detach privileges from roles

tyro:login

Mint a Sanctum token using user ID or email (respects suspensions)

tyro:quick-token

Mint a Sanctum token by user ID/email without password prompt

tyro:me

Paste a Sanctum token and see which user/abilities it belongs to

tyro:logout

Revoke a single token for a given user

tyro:logout-all

Revoke every token for a given user

tyro:logout-all-users

Revoke every Sanctum token for every user (emergency rotation)

tyro:seed-privileges

Reapply Tyro's default privilege catalog and role mappings

tyro:purge-privileges

Remove all privileges and detach them from every role

tyro:version

Echo the current Tyro version from configuration

tyro:postman-collection

Open (or print) the official Postman collection URL

tyro:star

Opens the GitHub repo so you can give Tyro a ⭐

tyro:doc

Opens the documentation site (or prints the URL with --no-open)

tyro:about

Summarises Tyro's mission, author, and useful links

All commands support --help flag and non-interactive mode for automation

View Full Command Reference

Frequently Asked Questions

Everything you need to know about Tyro

Tyro is the ultimate Authentication, Authorization, and Role & Privilege Management solution for Laravel 12. It provides complete RBAC, user suspension workflows, 40+ CLI commands, 7 Blade directives (@usercan, @hasrole, @hasanyrole, @hasroles, @hasprivilege, @hasanyprivilege, @hasprivileges), middleware for route protection, and optional REST API endpoints. It works for APIs, traditional web apps, and hybrid applications—saving you weeks of development time.

Tyro requires PHP 8.2 or higher, Laravel 12.0 or higher, and Laravel Sanctum 4.0 or higher. It's designed to work seamlessly with fresh Laravel installations and can be integrated into existing projects.

Installation is simple: run composer require hasinhayder/tyro followed by php artisan tyro:install. The install command automatically sets up Sanctum, runs migrations, seeds default roles and privileges, and prepares your User model. That's it—your API is ready!

Tyro ships with 40+ artisan commands for managing users, roles, privileges, tokens, and more. Key commands include: tyro:create-user, tyro:assign-role, tyro:suspend-user, tyro:add-privilege, tyro:attach-privilege, tyro:quick-token, and tyro:logout-all-users. Every command supports non-interactive flags for automation.

Tyro uses a flexible role-privilege system. Roles (like "admin", "editor") can have multiple privileges (like "reports.run", "billing.view"). Users are assigned roles, and they inherit all privileges from those roles. You can check permissions using $user->can('privilege.name'), $user->hasRole('role-slug'), or middleware like ability:admin,reports.run. Sanctum tokens automatically include all role and privilege slugs as abilities.

Absolutely! Publish the config file with php artisan vendor:publish --tag=tyro-config to customize route prefixes, middleware, table names, default roles, and more. You can also publish migrations and disable built-in routes or commands via environment variables. Tyro is designed to be extensible without friction.

Use php artisan tyro:suspend-user --user=email@example.com --reason="Policy violation" or call $user->suspend('reason') in your code. Suspension automatically revokes all Sanctum tokens and prevents login. To lift a suspension, use php artisan tyro:unsuspend-user or $user->unsuspend(). Check suspension status with $user->isSuspended().

Yes! Tyro is battle-tested and ships with the same security hardening, middleware stack, and authorization logic used in production applications. It includes comprehensive tests, factories, seeders, and follows Laravel best practices. You can disable commands in production via TYRO_DISABLE_COMMANDS=true for additional security.

Visit the GitHub repository to read the full documentation, open issues, or submit pull requests. The README includes detailed examples, API references, and troubleshooting guides. You can also use php artisan tyro:doc to open the documentation directly from your terminal.

Ready to Secure Your Laravel App?

Join developers who save weeks on authentication and authorization with Tyro

composer require hasinhayder/tyro