laravelcollective/auth
Legacy Laravel Collective authentication scaffolding for Laravel apps, providing login, registration, password reset, routes, controllers, and views to help add session-based user authentication quickly.
This package is a scaffolding generator, not a runtime auth engine — it republishes the classic Laravel 5-era auth controllers, routes, and Blade views (the pieces that used to ship with php artisan make:auth) so you can drop them into a modern app. Treat it as a one-time code generator whose output lives in your app/ and resources/ directories.
Minimal steps
composer require laravelcollective/auth
config/app.php:'providers' => [
// ...
LaravelCollective\Auth\AuthServiceProvider::class,
],
ls vendor/laravelcollective/auth/src
cat vendor/laravelcollective/auth/README.md
You are looking for the publish/install command name (commonly make:auth or a vendor:publish tag) and the controller namespace it targets.
php artisan vendor:publish --provider="LaravelCollective\Auth\AuthServiceProvider"
# or, if the package ships a generator command:
php artisan make:auth
app/Http/Controllers/Auth/* (LoginController, RegisterController, ForgotPasswordController, ResetPasswordController)routes/web.php (or a routes/auth.php to include)resources/views/auth/* and a layouts/app.blade.phpHomeControllerusers table plus a password reset table:php artisan migrate
php artisan route:list --path=login
php artisan route:list --path=password
Then hit /login and /register.
Where to look first: routes/web.php (or routes/auth.php) tells you exactly which controller methods are wired up, and app/Http/Controllers/Auth/LoginController.php tells you which traits are in play. Those two files are the map for everything else.
First real use case: a fresh Laravel app that needs plain email + password login, registration, logout, and password reset without pulling in Breeze/Jetstream/Fortify's frontend stack — or an old Laravel 5 app being lifted onto a current framework version where make:auth no longer exists.
Pattern 1 — Treat the scaffold as owned code, immediately.
Once published, edit the controllers freely. The package's job is done at publish time. Pin the version in composer.json and, if you want maximum stability, move it to require-dev after scaffolding — but only once you've confirmed no published file resolves classes from the vendor namespace at runtime (check the use statements in the generated controllers for LaravelCollective\Auth\...).
Pattern 2 — Customize by overriding trait methods, not by rewriting controllers.
The generated controllers are thin wrappers over traits (AuthenticatesUsers, RegistersUsers, ResetsPasswords, SendsPasswordResetEmails). Standard override points:
// app/Http/Controllers/Auth/LoginController.php
protected $redirectTo = '/dashboard';
protected function redirectTo(): string
{
return auth()->user()->isAdmin() ? '/admin' : '/dashboard';
}
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request) + ['tenant_id' => tenant()->id],
$request->filled('remember')
);
}
Same idea for RegisterController::create() (add fields, dispatch a welcome job) and ResetPasswordController::reset().
Pattern 3 — Add login throttling explicitly.
Older scaffolds predate the ThrottlesLogins trait being wired in. Verify it's present; if not, add it:
use Illuminate\Foundation\Auth\ThrottlesLogins;
protected $maxAttempts = 5;
protected $decayMinutes = 1;
and call $this->hasTooManyLoginAttempts($request) / $this->incrementLoginAttempts($request) / $this->clearLoginAttempts($request) inside login().
Pattern 4 — Modernize string controller routes.
Older generated routes use the string syntax 'Auth\LoginController@login', which silently breaks on Laravel 8+ when RouteServiceProvider::$namespace is null. Convert on publish:
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\RegisterController;
Route::middleware('guest')->group(function () {
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);
Route::get('register', [RegisterController::class, 'showRegistrationForm'])->name('register');
Route::post('register', [RegisterController::class, 'register']);
});
Route::post('logout', [LoginController::class, 'logout'])
->middleware('auth')->name('logout');
Pattern 5 — Views: swap Blade markup, keep the form contract.
The generated views are plain Blade with csrf_field(), old('email'), and @error blocks. Keep the field names (email, password, password_confirmation, remember, token) — the controllers and validation rules depend on them. Restyle the markup, don't rename inputs.
Pattern 6 — Compose with the rest of the Collective stack only when needed.
If the generated views use Form::open() / Html::link(), you must also install:
composer require laravelcollective/html
Otherwise every auth page throws Class 'Form' not found. If you'd rather not add that dependency, rewrite the two or three form blocks in the published views to plain HTML — usually the smaller change.
Pattern 7 — Extend with standard Laravel auth features.
Because the output is idiomatic Laravel, everything composes: MustVerifyEmail on User + verified middleware, custom guards in config/auth.php, Auth::routes(['register' => false])-style toggling (if the package exposes a routes macro), social login via Socialite wrapped around attemptLogin(), and multi-guard admin/customer splits in config/auth.php.
Pattern 8 — Test the generated controllers, not the package.
public function test_user_can_login(): void
{
$user = User::factory()->create(['password' => bcrypt('secret')]);
$this->post('/login', ['email' => $user->email, 'password' => 'secret'])
->assertRedirect('/dashboard');
$this->assertAuthenticatedAs($user);
}
Cover: successful login, bad password, throttling lockout, registration validation, password reset token flow, and logout. These are exactly the paths a stale scaffold is most likely to get wrong on a new Laravel version.
Integration tip: wrap the whole scaffold install in a single commit (git commit -m "scaffold auth") before you touch anything. Diffing against that commit is the fastest way to see exactly what the package changed in your app.
License is NOASSERTION. GitHub could not identify a license file. For anything beyond a prototype, read vendor/laravelcollective/auth/LICENSE (if it exists) and get a human to sign off. This is the single biggest blocker for production use.
It's a scaffold, not a maintained auth layer. laravel/ui, Breeze, Fortify, and Jetstream are first-party and actively patched against security advisories. With 13 stars, this package has essentially no security response capacity. Use it if you specifically want the old look and feel, or you're migrating a legacy app. Otherwise, Breeze is the lower-risk path and produces very similar files.
String controller routes are the #1 breakage. On Laravel 8+, 'Auth\LoginController@login' fails unless RouteServiceProvider::$namespace is set to 'App\Http\Controllers'. Symptom: Target class [Auth\LoginController] does not exist, or a 500 on POST. Fix with array callables + use imports.
Method-name drift between eras. Laravel 5.1 style: getLogin, postLogin, getRegister, postRegister, getLogout. Laravel 5.3+ style: showLoginForm, login, register, logout. The package may ship either depending on tag. Always cross-check generated controllers against php artisan route:list — a route pointing at a nonexistent method throws only when hit, not at boot.
Name collision with laravel/ui. Both packages historically register a make:auth command. If both are installed, one silently wins. Don't install both; if you must, uninstall laravel/ui first.
vendor:publish without --force is safe, with --force is destructive. It will overwrite your customized LoginController and views. Never run it with --force after you've started editing. Consider --tag= to publish selectively.
Do not publish config/auth.php. That's Laravel's own config file, not the package's. Overwriting it resets your guards and password broker settings. If the package offers a config publish tag, check what it targets before running it.
Password reset silently fails if the broker isn't configured. config/auth.php → passwords.users.table must match your migration (password_reset_tokens on Laravel 10+, password_resets on older). A mismatch produces "This password reset token is invalid" for every request. Also verify the User model uses CanResetPassword and Notifiable.
The remember me cookie depends on session config. If SESSION_DRIVER=array in testing, "remember" assertions fail. Use database or file and RefreshDatabase (plus the sessions table) for realistic tests.
Generated views may assume Bootstrap 3/4 classes. The markup is from an older era. If your app uses Tailwind or Bootstrap 5, expect to rewrite the views — budget for it rather than fighting the CSS.
Email verification is usually not included. Older scaffolds predate the verified middleware. If you need it, add MustVerifyEmail to User, add the verified middleware to protected routes, and wire VerificationController yourself (or copy it from a newer Laravel skeleton).
Debugging checklist when login "just doesn't work":
php artisan route:list --path=login — does the route exist and point at a real method?dd(class_uses(App\Http\Controllers\Auth\LoginController::class)) — are the expected traits there?guest middleware on the GET route and auth on logout?$redirectTo point at a route that exists?php artisan config:clear — a cached config from before install is a common culprit.Extension point worth knowing: because the whole thing is published code, the cleanest long-term move is to scaffold once, delete the package from composer.json, and maintain the resulting controllers/views as ordinary app code. You keep the classic UX with zero dependence on an unmaintained dependency.
How can I help you explore Laravel packages today?