I have built an login form using the default methods available in the Auth\LoginController.php.
Configured an AutoCliker to press the login button (the default login fields where autocompleted to simulate an unsuccessful login).
The hasTooManyLoginAttempts method from ThrottleLogins trait was disabled.
I. First problem was related to the TokenMismatchException trowed randomly on login failure.
This was fixed by catching the exception in Handler.php inside the render method.
app/Exceptions/Handler.php
if ($request->route()->named(['login_post','login'])) {
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()
->route('login')
->withInput($request->except('password', '_token'))
->withErrors(['error' => 'Validation Token was expired.']);
}
}
II. Now with this problem resolved when 'brute forcing' the login i realized that, sometimes (randomly), when AUTH failed no error messages where shown on the page.
First i thought that session was somehow not working (randomly) so i switched from session driver 'file' to 'redis' server. Same thing but checking the redis stored cache revealed that sometimes the cache name reverted from "myapp_cache' to 'laravel_cache'. Digging deeper i found out that somehow the '.env' file fails randomly (this happend to the sql server too, getting an QueryException) and the fallback where the files in the 'config' folder. So deleting '.env' and using Laravel's normal config files resoved this.
Now the cache was ok, but the same problem persisted (randomly not showing login failure messages).
After some hours of logging and going trough Laravel's AUTH i managed to restrain the search field to the 'sendFailedLoginResponse' method from 'AuthenticatesUsers' trait. Trowing an 'ValidationException' sometimes just redirects the user to the Login without the Session ErrorBag.
I managed to quick fix this, replacing (inside sendFailedLoginResponse)
\vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
with
return redirect()
->route('login')
->withInput($request->except('password', '_token'))
->withErrors(['error' => 'Auth failed']);
It appears that after doing this change the 'TokenMismatchException' redirect was not needed inside 'Handler.php'.
I hope this could help on fixing this problem. For more details don't hesitate to ask. Thanks.
EDIT:
PS: If somehow session data is lost you need the 'TokenMismatchException' redirect inside Handler.php.
Try to make the session bigger (with random data), and you may see that its all because of "race condition", old data was not saved and new data arrived. (I may be wrong, but worth the shot).
How fast is your auto-clicker clicking, can't you make Dusk test suite for this?
I will make the session bigger. Auto-clicker was clicking every 1000ms. Enough for Apache to process post and get.
I did now know about Dusk. Ill make a test.
This might be helpful for you, regarding the .env failure.
https://github.com/laravel/framework/issues/8191
Thanks @askaoru . Ill try with 'php artisan config:cache'.
@Kyslik I have made some Dusk tests:
class LoginFailTest extends DuskTestCase{
public function testExistingUser(){
$this->browse(function ($browser) {
$browser->visit('/login')
->clear('email')
->type('email', '[email protected]')
->clear('password')
->type('password', 'secret')
->press('Login')
->assertSee('Auth failed');
});
}
public function testUnknownUser(){
$this->browse(function ($first, $second) {
$first->visit('/login')
->clear('email')
->type('email', "[email protected]")
->clear('password')
->type('password', 'secret')
->press('Login')
->assertSee('Auth failed');
$second->visit('/login')
->clear('email')
->type('email', "[email protected]")
->clear('password')
->type('password', 'secret')
->press('Login')
->assertSee('Auth failed');
});
}
public function testNewUser(){
$random = "".substr(md5(mt_rand()), 0, 10)."@gmail.com";
$this->browse(function ($browser) use ($random) {
$browser->visit('/register')
->clear('name')
->type('name', 'Username')
->clear('mail')
->type('mail', $random)
->clear('pass')
->type('pass', 'secret')
->clear('passc')
->type('passc', 'secret')
->press('Register')
->pause(1000)
->visit('/login')
->clear('email')
->type('email', $random)
->clear('password')
->type('password', 'secret_broke')
->press('Login')
->assertSee('Auth failed');
});
}
}
All tests return OK.
Most helpful comment
This might be helpful for you, regarding the .env failure.
https://github.com/laravel/framework/issues/8191