Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Yes Authority Laravel Package

livelyworks/laravel-yes-authority

LivelyWorks Yes Authority is a Laravel package for role- and permission-based access control. It helps define roles, assign permissions, and protect routes and views with simple authorization checks.

View on GitHub
Deep Wiki
Context7

Getting Started

Where to look first (in this order):

  1. config/yes-authority.php — this is the whole mental model of the package. It contains two reciprocal maps plus a couple of escape hatches:
    • role_vs_authority — role name → list of authority strings
    • authority_vs_route — authority string → list of route names
    • super_user_role — a role that bypasses everything
    • check_route_name / skip_route_name_list — global on/off and exemptions
  2. The service provider — confirm the middleware alias it registers (commonly yes-authority) and the facade binding (YesAuthority).
  3. The middleware class — this is where the current route name is resolved and matched against authority_vs_route. Read it once; it is small and removes all ambiguity.
  4. The facade — exposes the ad-hoc check helpers (check, checkAll, checkRole, isSuperUser, isAuthorized) you will call from controllers, views, and tests.

Minimal install:

composer require livelyworks/laravel-yes-authority
php artisan vendor:publish --provider="LivelyWorks\YesAuthority\YesAuthorityServiceProvider" --tag=config

Configure the two maps:

// config/yes-authority.php
return [
    'role_vs_authority' => [
        'admin'   => ['users.view', 'users.manage', 'billing.view'],
        'manager' => ['users.view', 'billing.view'],
        'staff'   => ['users.view'],
    ],
    'authority_vs_route' => [
        'users.view'   => ['admin.users.index', 'admin.users.show'],
        'users.manage' => ['admin.users.create', 'admin.users.edit', 'admin.users.destroy'],
        'billing.view' => ['admin.billing.*'],
    ],
    'super_user_role'   => 'superadmin',
    'check_route_name'  => true,
    'skip_route_name_list' => ['login', 'logout', 'password.*', 'health'],
];

First use case — protect an admin area:

Route::middleware(['auth', 'yes-authority'])
    ->prefix('admin')
    ->name('admin.')
    ->group(base_path('routes/admin.php'));

Every named route in that file must appear under some authority in authority_vs_route or the request fails. That last sentence is the entire value proposition of the package: the config file becomes an auditable, diffable allow-list of route names.

The package assumes your user model exposes a role (a role column or equivalent accessor). Verify the exact expectation in the middleware before wiring it into an existing app; if your roles live in a pivot table you will need a small accessor or a fork.


Implementation Patterns

Group by audience, not by controller. Split routes into routes/admin.php, routes/staff.php, routes/public.php and attach the middleware per group. This keeps the authority_vs_route map tidy and makes it obvious which file corresponds to which block of config.

Wildcards for CRUD clusters. 'admin.billing.*' covers the resource routes in one line. Prefer an explicit list for anything destructive (destroy, forceDelete, impersonate) so a reviewer sees it in the diff.

Middleware for pages, facade for actions. Use the middleware for route-level gating and call the facade for capability checks that do not map 1:1 to a route — bulk actions, conditional buttons, JSON endpoints with a single URI and many operations:

public function bulkArchive(Request $request)
{
    abort_unless(YesAuthority::check('users.manage'), 403);
    // ...
}

Blade for navigation. Wrap menu items so the UI matches the middleware:

@yesAuthority('users.manage')
    <a href="{{ route('admin.users.index') }}">Manage users</a>
@endyesAuthority

Keep the authority string identical to the one in authority_vs_route; do not invent a second vocabulary.

Super-user bypass is an escape hatch, not a role. Use it for a single break-glass account (an on-call engineer, a migration script). If half your team is superadmin, the config maps are dead weight and you have lost the audit trail.

Overlay on Laravel's native stack, do not replace it. Route-name authorization answers "can this role reach this endpoint", not "can this user edit this record". Keep Policies for model-level rules ($this->authorize('update', $post)) and let YesAuthority handle the coarse gate in front. A request passes through middleware first, then the controller policy — that ordering is correct.

Testing. Because the source of truth is config, tests are cheap:

public function test_staff_cannot_reach_user_management(): void
{
    $this->actingAs(User::factory()->create(['role' => 'staff']))
        ->get(route('admin.users.edit', 1))
        ->assertForbidden();
}

public function test_every_named_admin_route_has_an_authority(): void
{
    $mapped = collect(config('yes-authority.authority_vs_route'))->flatten();
    // assert every route in routes/admin.php appears in $mapped
}

That second test is the highest-value thing you can add: it converts "someone added a route and forgot the config" from a silent security hole into a red CI run.

Config-cache discipline. In production the maps are read from bootstrap/cache/config.php. After editing yes-authority.php you must php artisan config:cache — a route:cache alone will not pick it up, and this is the single most common "the permission change didn't deploy" bug.

DB-backed authorities, if you outgrow config. If roles become editable by customers, keep the route→authority map in config but resolve role→authority from the database through a small service that the facade or a custom binding consults. Do not put mutable data in a cached config file.


Gotchas and Tips

Unnamed routes are the silent failure mode. With check_route_name enabled, routes without a ->name() cannot be matched against the map. Either they fail closed (safe but noisy) or slip through (unsafe). Run php artisan route:list --except-vendor and audit for blank names before turning the middleware on globally.

Renaming a route silently removes protection. The map keys on strings, so admin.users.edit → admin.users.update drops the authority without any error. Add the coverage test above and treat route names as an API surface.

Middleware order matters. auth must run before yes-authority, otherwise the middleware sees no user and either 403s everyone or (worse, depending on config) treats the request as a super-user context. Check group ordering in app/Http/Kernel.php and in your route files.

Null or unexpected roles. A user with role = null, an empty string, or a role absent from role_vs_authority should resolve to no authorities. Confirm in the middleware rather than assuming; a loose in_array on a null can surprise you, and the difference between fail-open and fail-closed is the whole ballgame.

Wildcards are prefix-ish, not regex. admin.billing.* behaves as a string match on the route-name segment; do not expect {param} interpolation or arbitrary patterns. If you need expressive matching, keep the map literal and branch in a Policy.

Super-user bypass masks config drift. Test with a normal admin user, not your superadmin. Every time you run a manual smoke test as the super user you learn nothing about the maps.

No migrations, no UI, no seeding. The package is exclusively an authorization decision layer. Role assignment, role editing screens, and audit logging of permission changes are yours to build. That is fine for a small app and is a real cost at scale.

Maintenance risk is the dominant concern here. Seven stars, zero dependents, last release February 2023. If you are on Laravel 10/11, check composer.json constraints before adopting — a ^9.0 illuminate constraint will not resolve. Budget for the possibility of vendoring or forking the two or three small classes; the surface area is genuinely tiny, so a fork is cheap. The upside of that smallness is that a security review of the package is an afternoon, not a sprint — do read the middleware and facade line by line rather than trusting the README, and pin the version in composer.json with a ~ constraint.

Debugging checklist when a page 403s unexpectedly:

dump(YesAuthority::getAll());                 // authorities the user resolved to
dump(auth()->user()->role);                  // the role the packge actually read
dump(request()->route()->getName());         // the name being matched
php artisan route:list --path=admin         // confirm names, middleware, order
php artisan config:clear && php artisan config:cache

Ninety percent of incidents are one of: wrong route name in the map, stale config cache, or a role string that does not match its config key (case, whitespace, pluralization).

Skip-list hygiene. skip_route_name_list is a bypass list. Put webhooks, health checks, and public marketing pages there — never anything under /admin. Grep the skip list during code review as carefully as you would grep a withoutMiddleware call.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast