Broken Authentication in Laravel
Laravel provides a comprehensive auth system with guards, middleware, and policies. However, broken auth occurs when middleware is applied inconsistently, when session regeneration is skipped after login, and when password reset tokens are not properly invalidated.
Scan Your Laravel AppHow Broken Authentication Manifests in Laravel
Broken auth in Laravel appears as: Routes missing the auth middleware, especially in resourceful controllers where some actions are protected but others are not. Session fixation after login when Session::regenerate() is not called (Laravel's built-in auth handles this, but custom auth flows often miss it). Password reset tokens that do not expire or are not single-use, allowing reuse attacks. APIs that accept user IDs from the request instead of deriving them from the authenticated session.
Real-World Impact
A Laravel application had a custom auth implementation that did not regenerate the session after login. An attacker set a known session ID on the victim's browser (via a subdomain cookie), waited for the victim to log in, then used the same session ID to access the authenticated session.
Step-by-Step Fix
Apply auth middleware at the route group level
Protect entire route groups instead of individual routes to prevent gaps.
// routes/web.php
// UNSAFE - easy to forget middleware on new routes
Route::get('/dashboard', [DashController::class, 'index'])->middleware('auth');
Route::get('/dashboard/settings', [SettingsController::class, 'index']); // Forgot middleware!
// SAFE - group-level middleware
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', [DashController::class, 'index']);
Route::get('/dashboard/settings', [SettingsController::class, 'index']);
Route::resource('projects', ProjectController::class);
});Regenerate session on login
Prevent session fixation by regenerating the session ID after authentication.
// Custom login (if not using built-in auth)
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate(); // Critical!
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Invalid credentials.',
]);
}Use Auth::id() for user identity
Never trust user IDs from request input. Always use the authenticated session.
// UNSAFE - user ID from request
public function show(Request $request)
{
$userId = $request->input('user_id');
$profile = User::findOrFail($userId);
return view('profile', compact('profile'));
}
// SAFE - user ID from authenticated session
public function show()
{
$profile = Auth::user();
return view('profile', compact('profile'));
}Prevention Best Practices
1. Apply auth middleware consistently to all protected routes, preferably at the route group level. 2. Always regenerate the session after login: $request->session()->regenerate(). 3. Use Laravel's built-in auth scaffolding (Breeze, Jetstream) which handles security properly. 4. Derive user identity from Auth::id(), never from request input. 5. Configure password reset token expiration in config/auth.php.
How to Test
1. List all routes with php artisan route:list and check which have auth middleware. 2. Try accessing protected URLs without logging in. 3. Check if session ID changes after login (compare cookie before/after). 4. Test password reset tokens for reuse and expiration. 5. Use Vibe App Scanner to detect broken auth in your Laravel application.
Frequently Asked Questions
Does Laravel Breeze/Jetstream handle auth securely?
Yes. Laravel's official auth scaffolding handles session regeneration, CSRF protection, password hashing, and rate limiting properly. Custom auth implementations often miss these security measures. Use Breeze or Jetstream as a starting point.
How do I implement role-based auth in Laravel?
Use Laravel's Gate and Policy system for authorization. Define abilities in AuthServiceProvider and check them with $this->authorize() in controllers or @can in Blade templates. For complex roles, use a package like Spatie Laravel Permission.
Are Laravel Sanctum tokens secure?
Yes, when used correctly. Sanctum tokens are hashed before storage, support expiration, and can be scoped to specific abilities. Ensure tokens are transmitted over HTTPS and stored securely on the client side.
Related Security Resources
Is Your Laravel App Vulnerable to Broken Authentication?
VAS automatically scans for broken authentication vulnerabilities in Laravel applications and provides step-by-step remediation guidance with code examples.
Scans from $5, results in minutes. Get actionable fixes tailored to your Laravel stack.