You might have a couple of options here:
Option 1. Asking the user for his/her ip-address
The simplest and most straightforward option would be requesting the user to provide his/her ip-address. You could point him/her to a websites or page within your application that displays the ip-address.
Option 2. Storing lock-outs to database
Storing the ip-address to the database after the user has been temporary blocked because of multiple failed login attempts would indeed also work. You can use the Illuminate\Auth\Events\Lockout event for this, which is triggered after each login attempt while the user is locked-out.
A small cavaet emptor: the login throthling data is likely stored on purpose using the cache system, as this takes the load of your database in case of a hacker of bot trying to bruteforce login details. Simply storing each failed attempt after the Lockout event is triggered would flood your database in a case of such a bruteforce attack.
You could circumvent this by using a 3rd cache key which you could use to determine whether or not the Lockout has already been stored to the database.
Example {$username}|{$ipAddress}:lockoutstoredtodb
<?php namespace App\Listeners\Auth;
use App\LockoutLogEntry;
use Illuminate\Auth\Events\Lockout;
use Cache;
class RegisterLockout{
public function handle(Lockout $lockoutEvent){
//Getting the ip-address and email-address
$ipAddress = $lockoutEvent->request->getClientIp();
$username = $lockoutEvent->request->input('email');
// Unique cache key used to determine whether or
$cacheKey = "{$username}|{$ipAddress}:lockoutstoredtodb";
// Only store a max. of one entry per hour
$secondsToWaitUntilStoringNextEntry = 60 * 60;
//Store new lockout log entry if not recently stored yet
Cache::remember($cacheKey, $secondsToWaitUntilStoringNextEntry, function () use($username, $ipAddress) {
return LockoutLogEntry::create(['username' => $username,
'ipaddress' => $ipAddress])->id;
});
}
}
Option 3. Temporarily white-listing a user
Not really recommended, but a third option could be creating a "whitelist" feature; completely disabling the throttling for a given amount of time for a specific user.
You should take into account that this would open the door for bruteforce attacks during the time a user is white-listed.
-
Store a key to your cache indicating that the user should be whitelisted. I.e. something like:
Cache::store("throthling_whitelist:{$username}", $whiteListTimeInSeconds);
-
Add something like a CheckForThrottlingWhitelist event listener to the Illuminate\Auth\Events\Attempting Event. Reset throttling keys for the user while being whitelisted. Quick example:
<?php namespace App\Listeners\Auth;
use Illuminate\Auth\Events\Attempting;
use Cache;
use Illuminate\Cache\RateLimiter;
class CheckForThrottlingWhitelist{
public function handle(Attempting $attemptingEvent){
$username = $attemptingEvent->credentials['email'];
$ipAddress = request()->getClientIp();
//Skip if white-listing has not been enabled for user
if(!Cache::has('throttling_whitelist:{$username}')) return;
//Reset any stored throttling cache keys for current user on current ipAddress
app(RateLimiter::class)->clear("{$username}|{$ipAddress}");
}
}
- Preferably disable the white-listing after a successful login. (You can use the
Authenticated event)
Note: the examples above assume Laravel 5.8+ is being used, which uses seconds when specifying the time a cached value should be stored. If you're using Laravel 5.7 or lower you can use minutes instead.