You’re describing a common but frustrating Laravel issue where a login form submits, but the page just refreshes with no visible errors, and the user isn’t logged in or redirected.
Since you’ve already confirmed the basics (CSRF token, POST method, correct route, and credentials in DB), here’s a checklist of deeper causes and how to fix them.
1. Wrong Input Names in Form
The Auth::attempt()
function looks specifically for email
(or username
, depending on your setup), and password
.
If your form uses:
<input type="text" name="user">
<input type="password" name="password">
But your controller does:
$request->only('username', 'password')
Then username
is null, and Auth::attempt()
silently fails.
Fix: Ensure form input names match exactly:
<input type="text" name="username" />
<input type="password" name="password" />
2. Validation Fails Silently
If you’re validating the request using validate()
or FormRequest
but don’t show errors in your Blade template, it’ll just redirect back without visible issues.
Check:
- Are you using
$request->validate([...])
?
- Do you have
@error('field') ... @enderror
in the Blade?
Fix: Add error display in your form:
@error('username')
<div class="text-red-500 text-sm">{{ $message }}</div>
@enderror
@error('login')
<div class="text-red-500 text-sm">{{ $message }}</div>
@enderror
3. No session
middleware
If your route group does not have web
middleware (or you’ve overridden middlewareGroups
in Kernel.php
), sessions won’t persist — so even a successful login won’t stick.
Fix: Ensure routes are in the web
middleware group (this should be default in web.php
):
Route::middleware('web')->group(function () {
Route::get('/login', [LoginController::class, 'index'])->name('login');
Route::post('/login', [LoginController::class, 'authenticate']);
});
4. No Error Key Used in Blade
You’re returning errors like this:
return back()->withErrors(['login' => 'Invalid username or password.']);
Make sure in the Blade you check for it:
@if ($errors->has('login'))
<div class="text-red-500">{{ $errors->first('login') }}</div>
@endif
5. Password Not Hashed
If you’re inserting users manually in the DB and used plaintext passwords, Auth::attempt()
will fail. Laravel expects password
to be bcrypt-hashed.
Fix:
$user->password = Hash::make('secret123');
Or in tinker:
php artisan tinker
User::create(['username' => 'admin', 'password' => Hash::make('admin123')])
6. Rate Limiting or Throttling Middleware
If you have throttle
or LoginLimiter
middleware and hit too many attempts, Laravel might silently reject further logins.
Check routes/web.php
for throttle
:
Route::post('/login', [LoginController::class, 'authenticate'])->middleware('throttle:5,1');
7. Auth Guard Mismatch
If you’re using a custom guard in config/auth.php
but calling Auth::attempt()
without specifying the guard, it may silently fail.
Fix (if applicable):
Auth::guard('admin')->attempt($credentials)
8. CSRF Token Mismatch on Some Environments
If you have CSRF tokens but they’re stale or you’re submitting from JS/AJAX without setting the token correctly, Laravel will reject it without a visible error.
Check:
- Use
@csrf
- If in doubt, try disabling CSRF in middleware (not in production) to isolate the issue.
Summary Debug Plan
- Inspect the HTML form — do input names match what you’re using in the controller?
- Dump credentials in the controller:
dd($credentials);
- Log the result of
Auth::attempt()
:
if (Auth::attempt($credentials)) {
return redirect()->intended('/');
} else {
\Log::info('Login failed', ['credentials' => $credentials]);
return back()->withErrors(['login' => 'Invalid username or password.']);
}
- Ensure session middleware and
web
group are applied.