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

Aauth Laravel Package

aurorawebsoftware/aauth

AAuth is a Laravel package that adds a configurable authentication and authorization layer to your application, making it easier to manage guards, access control, and user permissions with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require aurorawebsoftware/aauth
php artisan vendor:publish --provider="AuroraWebSoftware\AAuth\AAuthServiceProvider"
php artisan migrate

The publish step is the important one — it drops config and migration files into your app. Read the config file first; it usually contains the table names, guard names, and any "super admin" bypass flag you'll need to align with your existing users table.

Where to look first

  1. config/aauth.php (or similarly named) — table names, model bindings, cache settings.
  2. The package's own migration stubs — check for foreign keys to users and whether they assume a specific primary key type (bigIncrements vs uuid).
  3. The service provider's boot() — this is where Blade directives, middleware aliases, and Gate integration are typically registered.
  4. The README's "Basic Usage" section — auth packages almost always get their usage documented there, but rarely their extension points.

First use case: gate one route

Add the package trait to your User model:

use AuroraWebSoftware\AAuth\Traits\HasAAuth;

class User extends Authenticatable
{
    use HasAAuth;
}

Seed a role and a permission, attach them, then protect a route:

Route::get('/reports', fn () => view('reports'))
    ->middleware('aauth.permission:reports.view');

If that works end-to-end, you've validated the migration, the trait, the guard wiring, and the middleware alias in one pass. Do this before writing any business logic — auth packages fail loudly at this boundary and it's cheap to fix now.

Implementation Patterns

Seeder-driven permission catalogue

The most maintainable pattern with any RBAC package is to treat permissions as data you define in code and roles as data you edit in the admin UI. Keep a canonical list:

// database/seeders/PermissionSeeder.php
$permissions = [
    'reports.view', 'reports.export',
    'users.invite', 'users.deactivate',
    'billing.view', 'billing.refund',
];

foreach ($permissions as $name) {
    AAuth::permission()->firstOrCreate(['name' => $name]);
}

Run this in every environment including production (--class=PermissionSeeder). It's idempotent, so it's safe on deploy, and it means "what permissions exist" is always answerable from git.

Controller checks vs. policies

Use the package's facade for coarse checks at the top of an action, and Laravel policies for per-record authorization:

public function refund(Invoice $invoice)
{
    abort_unless(AAuth::hasPermission('billing.refund'), 403);
    $this->authorize('refund', $invoice); // per-record logic in your Policy
}

This split keeps the package out of your domain rules. Model-specific authorization stays in Laravel's native policy system, which is easier to test and doesn't tie your business logic to a third-party API.

Blade conditional rendering

Most packages register a directive. Use it, but don't rely on it for security — it's a UI convenience only:

@aauth('billing.refund')
    <button wire:click="refund">Refund</button>
@endaauth

The same check must exist server-side in the Livewire component or controller. A hidden button is not authorization.

Route groups by permission

For admin areas, group routes so you don't repeat middleware:

Route::middleware(['auth', 'aauth.permission:admin.access'])
    ->prefix('admin')
    ->group(base_path('routes/admin.php'));

Keep permission names namespaced (admin.users.edit) so a route group maps to a permission prefix and you can audit coverage by grepping the routes file.

Entity/tenant scoping

If the package supports scoping permissions to a model instance (many Laravel RBAC packages do, via a polymorphic pivot), use it for multi-tenant apps rather than creating duplicate global permissions per tenant. Pattern:

AAuth::for($organization)->hasPermission('billing.refund')

Verify the exact API against the README — this is the single most version-sensitive part of these packages, and getting it wrong means permissions silently resolve against the wrong scope.

Testing

Write a small helper so tests stay readable:

protected function actingAsWithPermissions(array $perms, ?User $user = null): User
{
    $user = $user ?? User::factory()->create();
    $role = AAuth::role()->create(['name' => 'test-'.uniqid()]);
    $role->syncPermissions($perms);
    $user->assignRole($role);

    return $this->actingAs($user);
}

Because the package caches permission lookups, flush the cache in setUp() or your tests will leak state across cases.

Gotchas and Tips

Cache invalidation is the #1 source of "it works locally" bugs. Authorization packages cache the permission graph per user because it's expensive to query on every request. If you assign a role in an admin panel and the change doesn't take effect until the user re-logs in, it's the cache. Look for a flush/forget method on the facade and call it from your role-assignment actions, or disable the cache in local/test environments via config.

Watch for N+1 on permission checks in loops. AAuth::hasPermission() inside a @foreach over 200 rows may re-query per iteration depending on whether the eager-load is warm. Eager-load the roles/permissions relationship (the trait usually exposes something like ->with('roles.permissions')) or check the permission once before the loop and pass a boolean in.

Guard mismatch. If your app has multiple guards (web, admin, api), the package's middleware may default to one. A user authenticated on admin but checked against web will silently fail hasPermission() and return false rather than throwing — which reads as "permission missing" when the real problem is the guard. Confirm which guard the config points at before debugging your pivot tables.

Super-admin bypass is usually config-driven, not a permission. Many packages short-circuit hasPermission() to true for a flagged user or role. That means hasPermission() can return true for a permission that doesn't exist in the DB. Don't use hasPermission() as an existence check for "does this permission exist" — that's what the permission repository/query is for.

Migration ordering and key types. Published migrations often assume they run after users. If you have a custom users table with a uuid primary key, the package's user_id foreign key column will be the wrong type. Open the migration before running php artisan migrate and adjust — re-running migrations after the fact means dropping and recreating the pivot tables.

Middleware aliases must be registered. Some versions of these packages ship the middleware but expect you to register the alias in bootstrap/app.php (Laravel 11+) or Kernel.php. If you get "Target class [aauth.permission] does not exist", that's the missing registration, not a missing package install.

Prefer permission checks over role checks in application code. Checking hasRole('manager') scatters org-chart assumptions across controllers; checking hasPermission('reports.export') means you can reorganize roles in the admin UI without code changes. Reserve role checks for things that are genuinely about role identity (e.g., "only the owner role can transfer ownership").

Debugging checklist when a check unexpectedly fails:

  1. Is the user model using the trait? (A missing trait is silent — hasPermission may be an undefined-method error or, worse, resolve to a false stub.)
  2. Is the permission attached to a role that is attached to the user? Dump $user->roles()->with('permissions')->get().
  3. Is the cache stale? Flush and retry.
  4. Is the guard correct? AAuth::hasPermission() vs Auth::guard('admin')->user()->hasPermission().
  5. Does the permission name match exactly, including case and the dot.notation separator?

Extension points worth knowing before you need them. Look for an interface or binding for the permission-checker and for the role/permission models in config. If your app needs a custom role model (extra columns, soft deletes, team scoping), the config binding is usually the intended path — but binding it after you have production data means a risky migration, so decide early.

Low adoption signal. With effectively no dependents or community footprint, expect to read the source rather than find answers. Budget an hour to skim src/ before committing: specifically the service provider, the trait, and the middleware. That hour tells you more than the README, and it tells you whether the package's guard/cache assumptions match your app.

Have an exit ramp. Because authorization touches every controller, wrap the package behind a thin app-level service (App\Support\Authorization) that exposes can(User $u, string $permission): bool. Call that everywhere instead of the facade. If you ever need to swap to spatie/laravel-permission or native Gates, you change one file instead of two hundred.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings