laravel/sentinel
Laravel Sentinel adds simple, lightweight tools for monitoring and reporting within Laravel apps. Built as a package you can drop in to capture key events, surface issues, and gain basic operational visibility without heavy setup or external services.
Install via Composer:
composer require laravel/sentinel
Publish migrations and config:
php artisan vendor:publish --provider="Sentinel\SentinelServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Sentinel\SentinelServiceProvider" --tag="config"
Run migrations:
php artisan migrate
First Use Case: Authenticate a User
use Sentinel;
$user = Sentinel::authenticate(['email' => 'user@example.com', 'password' => 'password']);
if (Sentinel::check()) {
// User is authenticated
$user->roles; // Access roles
$user->permissions; // Access permissions
}
First Use Case: Check User Permissions
if (Sentinel::getUser()->hasAccess(['edit-post', 'delete-comment'])) {
// User has all required permissions
}
Login/Logout with Remember-Me
// Login with remember-me
Sentinel::authenticate(['email' => 'user@example.com'], false, true);
// Logout
Sentinel::logout();
Registration with Activation
$user = Sentinel::registerAndActivate([
'email' => 'user@example.com',
'password' => 'secure123',
'first_name' => 'John',
'last_name' => 'Doe',
'activated' => true, // Skip email activation
]);
Password Reset
$credentials = ['email' => 'user@example.com'];
$attempts = Sentinel::attemptReset($credentials, 'new-password');
if ($attempts) {
// Reset successful
}
Create and Assign Roles
$adminRole = Sentinel::createRole(['name' => 'admin']);
$user->roles()->attach($adminRole);
Check Role or Permission
if (Sentinel::getUser()->hasRole('admin')) {
// Admin logic
}
if (Sentinel::getUser()->hasAccess('edit-post')) {
// Permission granted
}
Bulk Role Assignment
$users = Sentinel::findWhere(['email' => ['like', '%@example.com']]);
$users->each->roles()->attach($adminRole);
Custom Role Middleware
// app/Http/Middleware/CheckRole.php
public function handle($request, Closure $next, $role)
{
if (!Sentinel::getUser()->hasRole($role)) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
Register Middleware in app/Http/Kernel.php
protected $routeMiddleware = [
'role' => \App\Http\Middleware\CheckRole::class,
];
Use in Routes
Route::get('/admin/dashboard', function () {
return view('admin.dashboard');
})->middleware('role:admin');
Configure in config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'sentinel',
],
'api' => [
'driver' => 'token',
'provider' => 'sentinel',
],
],
Switch Guards Dynamically
Sentinel::switchToGuard('api');
$user = Sentinel::authenticate(['api_token' => 'abc123']);
Mock Authentication in Tests
public function test_admin_access()
{
$admin = factory(\Sentinel\User::class)->create();
$admin->roles()->attach(Sentinel::createRole(['name' => 'admin']));
Sentinel::login($admin);
$this->actingAs($admin, 'sentinel')
->get('/admin')
->assertOk();
}
Assert Permissions
$this->assertTrue(Sentinel::getUser()->hasAccess('edit-post'));
$this->assertFalse(Sentinel::getUser()->hasAccess('delete-all'));
Database Table Conflicts
sentinel_users, sentinel_roles, and sentinel_permissions tables. If Laravel’s default users table exists, either:
users table.Deprecated Laravel Features
Hash::make()). Override in SentinelServiceProvider for Laravel 9+:
use Illuminate\Support\Facades\Hash;
$this->app->bind('hash', function () {
return Hash::getDriver();
});
No Active Development
Docker/Localhost Issues
Dockerfile mounts storage:
VOLUME ["/var/www/html/storage"]
php artisan sentinel:clear-cache
Permission Caching
Sentinel::clearResolvedPermissions();
Auth Conflicts
If Sentinel::user() and Auth::user() differ:
AuthServiceProvider:
protected $guards = [
'sentinel' => [
'driver' => 'session',
'provider' => 'sentinel',
],
];
Role/Permission Not Updating
dd(Sentinel::getUser()->roles->pluck('name'));
Throttling Issues
Sentinel::throttling(function ($user) {
return !$user->isAdmin(); // No throttling for admins
});
Custom User Model
Extend Sentinel\User and rebind in SentinelServiceProvider:
$this->app->bind('Sentinel.User', function () {
return new \App\Models\CustomUser();
});
Event Listeners
Listen to Sentinel events (e.g., activating, authenticated):
// app/Providers/EventServiceProvider.php
protected $listen = [
'Sentinel.activating' => \App\Listeners\LogActivation::class,
'Sentinel.authenticated' => \App\Listeners\SendWelcomeEmail::class,
];
Multi-Tenant Support
Override Sentinel::getUser() to scope by tenant:
Sentinel::extend(function ($app) {
$app['Sentinel'] = $app->share(function () {
return new Sentinel\Sentinel(new TenantAwareUserProvider());
});
});
Custom Permission Logic Extend permission checks:
Sentinel::extendPermissionLogic(function ($user, $permission) {
if ($permission === 'edit-post' && $user->isEditor()) {
return true;
}
return false;
});
$user = Sentinel::findById(1)->withRoles()->withPermissions();
$admins = Sentinel::all()->filter(fn($user) => $user->hasRole('admin'));
config/sentinel.php):
'debug' => env('APP_DEBUG', false),
Password Hashing
config/sentinel.php uses a secure hashing driver:
'hash_driver' => 'bcrypt',
Session Security
sanctum or api guards for token-based auth to avoid session fixation:
Sentinel::switchToGuard('api');
Permission Hardcoding
config(['sentinel.permissions' => ['edit-post', 'delete-comment']]);
From Sentinel to Modern Auth (e.g., Breeze/Jetstream)
$users = Sentinel::all();
foreach ($users as $user) {
\App\Models\User::updateOrCreate(
['email' => $user->email],
['password' => bcrypt(str_random(10))]
);
}
How can I help you explore Laravel packages today?