Integrate throttle in custom login using Laravel

In the case of user Authentication, Laravel has built-in Authentication system. We can easily modify it according to requirements. One of the features included in Authentication is Throttling.

Why we need throttling protection?

Basically, throttling is used to protect the brute-force attack. It will check the login attempts within a certain amount of time. In short login, throttling count the number of failed login attempts that a user or bot tries.

Implement Throttling with custom login

Throttling is by default implemented in the built-in authentication controller. But what if we need to implement it to the custom login?

It is very easy to implement throttling to custom login. First of all, we have to include the ThrottlesLogins trait to your controller.

use Illuminate\Foundation\Auth\ThrottlesLogins;

Now attach this ThrottlesLogins trait with your controller.

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ThrottlesLogins;

class AuthController extends Controller
{
    use ThrottlesLogins;

    ......

Now go to the method that you used to authenticate the user. In my cause, I have used login() POST method. And paste the following codes.

    public function login(Request $request)
    {
        // Authenticate Inputs
        $request->validate([
            'username' => 'required', 
            'password' => 'required|min:6|max:18'
        ]);


        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (method_exists($this, 'hasTooManyLoginAttempts') &&
            $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }
      
        .......

First, We have validated the input posted by the user and then implemented the hasTooManyLoginAttempts() method. This method will check if a user has done a certain number of failed attempts at a certain time then the system will block that user through sendLockoutResponse() method.

Now we have to indicate the failed login attempts to ThrottlesLogins trait through the incrementLoginAttempts() method.

        if( Auth::attempt(['username' => $username, 'password' => $password]) ){
            // Redirect to appropriate dashboard 
        }
        else {

            // If the login attempt was unsuccessful we will increment the number of attempts
            // to login and redirect the user back to the login form. Of course, when this
            // user surpasses their maximum number of attempts they will get locked out.
            $this->incrementLoginAttempts($request);

            return redirect()->back()
                ->withInput($request->all())
                ->withErrors(['error' => 'Please check your username / password.']);
        }

You can also change the maximum number of attempts to allow and the number of minutes to throttle for easily through the $maxAttempts and $decayMinutes properties. Here you find the complete code.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ThrottlesLogins;

class AuthController extends Controller
{
    use ThrottlesLogins;


    /**
     * The maximum number of attempts to allow.
     *
     * @return int
     */
    protected $maxAttempts = 5;


    /**
     * The number of minutes to throttle for.
     *
     * @return int
     */
    protected $decayMinutes = 1;


    public function login(Request $request)
    {
        // Authenticate Inputs
        $request->validate([
            'username' => 'required', 
            'password' => 'required|min:6|max:18'
        ]);


        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (method_exists($this, 'hasTooManyLoginAttempts') &&
            $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        $username = $request->username;
        $password = $request->password;

        
        if( Auth::attempt(['username' => $username, 'password' => $password]) ){
            // Redirect to appropriate dashboard 
        }
        else {

            // If the login attempt was unsuccessful we will increment the number of attempts
            // to login and redirect the user back to the login form. Of course, when this
            // user surpasses their maximum number of attempts they will get locked out.
            $this->incrementLoginAttempts($request);

            return redirect()->back()
                ->withInput($request->all())
                ->withErrors(['error' => 'Please check your username / password.']);
        }
    }
}