n3xt0r/laravel-passport-modern-scopes
Attribute-based OAuth scope enforcement for Laravel Passport. Declare required scopes directly on controllers/actions via PHP 8 attributes, then enforce them with a single middleware. Keeps routes clean and auth rules close to the code they protect.
Installation
composer require n3xt0r/laravel-passport-modern-scopes
Run migrations:
php artisan migrate
Publish Config
php artisan vendor:publish --provider="N3xt0r\PassportModernScopes\PassportModernScopesServiceProvider" --tag="config"
Review config/passport-modern-scopes.php for default scope definitions.
First Use Case
Define a scope in config/passport-modern-scopes.php:
'scopes' => [
'admin' => [
'attributes' => ['role' => 'admin'],
],
'user:profile' => [
'attributes' => ['user_id' => auth()->id()],
],
],
Assign scopes to a user:
$user->scopes()->sync(['admin', 'user:profile']);
Assign Scopes Dynamically
// In a controller or service
$user->scopes()->sync($request->scopes);
Check Scopes in API
// Middleware or controller
if (!PassportModernScopes::hasScope('admin')) {
abort(403, 'Admin scope required');
}
Scope-Based Route Groups
Route::middleware(['auth:api', 'scope:admin'])->group(function () {
// Admin-only routes
});
Token Creation
$token = $user->createToken('API Token', ['admin', 'user:profile']);
Custom Scope Logic
Extend N3xt0r\PassportModernScopes\Scopes\Scope for complex rules:
class CustomScope extends Scope {
public function check($user, $request) {
return $user->isActive() && parent::check($user, $request);
}
}
'scopes' => [
'role:editor' => [
'attributes' => ['role' => ['editor', 'admin']],
],
],
'scopes' => [
'user:team' => [
'attributes' => ['team_id' => fn($user) => $user->team_id],
],
],
Scope Caching
php artisan passport-modern-scopes:clear-cache
PassportModernScopes::clearCache($user);
Attribute Mismatch
attributes in config match the user model’s fields. Use fn() for computed values:
'attributes' => ['team_id' => fn($user) => $user->currentTeam->id],
Middleware Conflicts
scope: middleware, ensure it runs after auth:api in $routeMiddleware.Token Scope Persistence
Log Scope Checks Enable debug mode in config:
'debug' => env('PASSPORT_SCOPES_DEBUG', false),
Check logs for failed scope validations.
Inspect User Scopes
dd($user->scopes); // Collection of assigned scopes
Custom Scope Classes
Override N3xt0r\PassportModernScopes\Scopes\ScopeResolver to add logic:
public function resolve($scopeName) {
return match ($scopeName) {
'vip' => new VipScope(),
default => parent::resolve($scopeName),
};
}
Event Listeners Listen for scope changes:
// In EventServiceProvider
protected $listen = [
'N3xt0r\PassportModernScopes\Events\ScopesSynced' => [
\App\Listeners\LogScopeChange::class,
],
];
API Resource Filtering
Use the PassportModernScopes::getAllowedAttributes() helper to filter Eloquent results:
$allowed = PassportModernScopes::getAllowedAttributes('user:profile');
return User::where($allowed)->get();
default_scopes in config to auto-assign scopes on user creation:
'default_scopes' => ['user:profile'],
user:profile) for consistency with Passport’s token scope format.How can I help you explore Laravel packages today?