taysonvo's avatar

How to unlock user from admin portal ?

Hi everyone,

I'm using Laravel/Auth ThrottlesLogins to set up the number of login failed attempt (5 times) and the waiting time to login again (15 mins).

For example, an user try to login failed 5 times and that user is locked and have to wait 15 mins to try again.

Is there a way that I can unlock that user from admin portal ? (ex: that user contact admin and need help to unlock immediately, he have urgent thing to do and cannot wait till 15 mins)

Thanks a lot!

0 likes
5 replies
vevers's avatar

ThrottlesLogins use Illuminate\Cache\RateLimiter to store any throttling data to the cache.

Two keys seem to be used: "{$username}|{$ipAddress}" to store the number of login attempts and "{$username}|{$ipAddress}:timer" which is used to block the user for a certain amount of time after he/she exceeded the max. number of login attempts.

You can reset both keys using: app(RateLimiter::class)->clear("{$username}|{$ipAddress}")

For example: app(RateLimiter::class)->clear("[email protected]|123.45.67.89")

1 like
taysonvo's avatar

Thank u, @vevers The problem is how I know the ip address of the login username from the Admin portal side. I might have to store it in somewhere may be table user... right after it get over 5 times attempted, I think.

vevers's avatar
vevers
Best Answer
Level 4

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.

  1. Store a key to your cache indicating that the user should be whitelisted. I.e. something like: Cache::store("throthling_whitelist:{$username}", $whiteListTimeInSeconds);

  2. 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}");
    } 
}
  1. 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.

Please or to participate in this conversation.