arcanedev/laravel-auth
An authentication package for Laravel that provides ready-made login, registration, and password reset scaffolding, along with user roles and permissions and customizable auth views for quickly securing an application.
Before you install anything, do the compatibility math. The last tagged release is from September 2018, which puts it in the Laravel 5.5–5.7 / PHP 7.0–7.1 era. With 26 stars and zero known dependents, there is no community safety net. Confirm it boots on your framework version first:
composer require arcanedev/laravel-auth
php artisan vendor:publish --provider="Arcanedev\LaravelAuth\LaravelAuthServiceProvider"
php artisan migrate
Publish tags are typically split (config, migrations, seeds) — publish them individually so you can diff what you're about to run against your existing users table. The config lands at config/authorization.php and is the single most important file to read: it controls table names, model bindings, and cache settings.
Where to look first, in order:
config/authorization.php — table names, swappable model classes, cache TTL.src/ — reveals registered middleware aliases and Blade directives (these are the public API surface).src/Traits/ — the trait you'll add to your User model (commonly HasRolesAndPermissions; confirm the exact namespace, as ARCANEDEV renamed things across minor versions).users table references and foreign keys before running in production.First use case: put a role gate on an admin route group and a permission check inside a controller. That's the 10-minute path to knowing whether the package is worth keeping.
// app/User.php
use Arcanedev\LaravelAuth\Traits\HasRolesAndPermissions;
class User extends Authenticatable
{
use HasRolesAndPermissions;
}
// routes/web.php
Route::middleware(['auth', 'role:admin'])->group(function () {
Route::get('/admin', AdminController::class);
});
// controller
abort_unless(auth()->user()->can('edit-posts'), 403);
If those three work, the package is functional for your version. If the trait or middleware alias is missing, stop and reassess — you're now debugging an abandoned dependency.
Seed roles and permissions declaratively, never by hand. The whole value of an ACL package is reproducibility across environments. Build one idempotent seeder that uses firstOrCreate on roles and permissions and re-syncs the pivot:
// database/seeds/RolesAndPermissionsSeeder.php
$admin = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
$edit = Permission::firstOrCreate(['slug' => 'edit-posts'], ['name' => 'Edit Posts']);
$admin->attachPermissions([$edit->id]); // verify method name in src/Entities or src/Models
$user->assignRole('admin'); // accepts slug or model — pick one convention and stick to it
Run this in every deploy after migrate. Treat the seeder as source of truth, not the database.
Layer three check styles, each for a different job:
| Layer | Use for | Example |
|---|---|---|
| Route middleware | Coarse route-group protection | ->middleware('permission:edit-posts') |
| Controller/Policy | Business-rule authorization | $this->authorize('update', $post) |
| Blade directive | Hiding UI affordances only | @role('admin') ... @endrole |
Never rely on the Blade directive for security — it only hides markup. The middleware or policy must be the enforcement point.
Bridge to Laravel's Gate so you get one authorization idiom. Rather than sprinkling package-specific calls everywhere, register a Gate::before for super-admins and let policies delegate to the permission check:
// AuthServiceProvider::boot()
Gate::before(function ($user) {
return $user->is('super-admin') ? true : null;
});
This means @can and $this->authorize() work throughout your app while permissions still live in the package's tables. It also makes a future migration to spatie/laravel-permission a config change rather than a rewrite — both expose hasPermissionTo-style checks you can alias.
Eager-load aggressively. Any index page listing users with roles will N+1 without it:
User::with('roles.permissions')->paginate(50);
Wrap role mutation in a service or job, not controllers. Role changes need cache invalidation and audit logging. One RoleAssignmentService::assign($user, $role) method calls the package, flushes the cache, and fires an event — that's your single seam when the package eventually gets replaced.
Maintenance risk is the headline gotcha. No release since 2018, 26 stars, no dependents. Expect breakage from removed helpers (str_slug, array_get, str_plural) if you're on Laravel 6+, and from $dates/$casts handling on Laravel 8+. If you're on Laravel 9+, assume it will not install without a fork. Budget for vendoring or pinning.
The can() method can collide with Laravel's own. The trait may define or override authorization helpers on the User model, and Laravel's Authorizable trait also provides can(). If permission checks silently return the wrong result, dump class_uses_recursive(User::class) and check method resolution order. Rename your call sites to package-specific methods (canOne, is, hasRole) to sidestep ambiguity.
Cache invalidation is the most common production bug. This class of package caches the permission map per user. Assign a role via raw query, a queue worker, or a seeder outside the package API and the user keeps stale permissions until TTL expiry. Always mutate through the package's methods, and add an explicit cache flush to any admin UI that edits roles.
Table name and foreign-key conflicts. The published migrations assume a users table with a bigIncrements id. UUID/ULID users, multi-tenant schemas, or a pre-existing roles table from another package will fail at migrate time. Edit the published migrations before running them, and check config/authorization.php for a table-prefix option.
Middleware alias registration. If role:admin throws "middleware not found," the alias is registered by the service provider — verify the provider is in config/app.php (or auto-discovered) and run php artisan route:list -v to confirm what's actually attached to the route.
Debugging workflow:
php artisan tinker
>>> $u = App\User::first();
>>> $u->roles; // is the relation even loaded?
>>> $u->can('edit-posts'); // package check
>>> Gate::forUser($u)->allows('edit-posts'); // Laravel check — compare
If the two disagree, you have a trait/collision problem, not a data problem.
Know the extension points before you need them. The config's model-swap keys let you subclass Role/Permission with your own logic (soft deletes, audit columns). Use this rather than forking the package — a one-class override is upgradeable; a fork is not.
Have an exit plan. Because the package is effectively unmaintained, write your permission checks against a thin internal interface (UserPermissions::can($user, $ability)) from day one. When you move to spatie/laravel-permission — which has active maintenance, Laravel 11 support, and a documented migration path — you swap one implementation class instead of grepping 200 call sites.
How can I help you explore Laravel packages today?