Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

randm's avatar

How to change the code for the built in Authentication in Laravel?

Hi,

I am trying to advance the built in Authentication system. I want to be able to do the following

  1. Log every login attempt in a new table
  2. Keep a history of the password used "to prevent the same password from being used in the past 6 months"
  3. I want to check if the user is logging in with in a set time frame (Between 7 AM - 5PM)
  4. I want to restrict some users from logging globally. Some uses will need to be in a trusted location to login using static IP.

I should be able to do the work as long as I know where to go to modify existing code and understand the existing code

Here is my routes.php content

// login routes
Route::get('auth/login', array(
    'as' => 'auth_login_getLogin',
    'uses' => 'Auth\AuthController@getLogin'
));

Route::post('auth/login', array(
    'as' => 'auth_login_postLogin',
    'uses' => 'Auth\AuthController@postLogin'
));

Route::get('auth/logout', array(
    'as' => 'auth_logout_getLogout',
    'uses' => 'Auth\AuthController@getLogout'
));

// Registration routes...
Route::get('auth/register', array(
    'as' => 'auth_register_getRegister',
    'uses' => 'Auth\AuthController@getRegister'
));

Route::post('auth/register', array(
    'as' => 'auth_register_postRegister',
    'uses' => 'Auth\AuthController@postRegister'
));


// Password reset link request routes...
Route::get('password/email', array(
    'as' => 'password_email_getEmail',
    'uses' => 'Auth\PasswordController@getEmail'
));

Route::post('password/email', array(
    'as' => 'password_email_postEmail',
    'uses' => 'Auth\PasswordController@postEmail'
));

// Password reset routes...
Route::get('password/reset/{token}', array(
    'as' => 'password_reset_getReset',
    'uses' => 'Auth\PasswordController@getReset'
));

Route::post('password/reset', array(
    'as' => 'password_reset_postReset',
    'uses' => 'Auth\PasswordController@postReset'
));

the first route aka "auth_login_getLogin" tells me that the code that will be executed should be in the following controller '\app\Http\Controllers\Auth\AuthController.php' I should be able to find a method called getLogin() where I can modify.

However, when I open the 'AuthController.php' file I only see 2 methods create() and valodator()

Where would I find the getLogin(), postLogin(), getLogout() method?

0 likes
8 replies
bimalshah72's avatar

AuthController using AuthenticatesAndRegistersUsers trait

it again uses AuthenticatesUsers trait

so getLogin methos you will find

Illuminate\Foundation\Auth\AuthenticatesUsers

3 likes
accent-interactive's avatar

The getLogin(), postLogin() and getLogout() methods are defined in the AuthenticatesUsers trait. Your AuthController use this trait.

vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

You can simply override the methods in AuthController if you need to.

3 likes
randm's avatar

Thank you @bimalshah72 and @joostvanveen

@joostvanveen, what is the best way to override the method inside the trait without having to change up the code?

Here is the code postLogin() method from the AuthenticatesUsers.php file.

    public function postLogin(Request $request)
    {
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);

        // 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.
        $throttles = $this->isUsingThrottlesLoginsTrait();

        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);

        if (Auth::attempt($credentials, $request->has('remember'))) {
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

        // 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.
        if ($throttles) {
            $this->incrementLoginAttempts($request);
        }

        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }

to do what I need I will need to do something like this "please check my comment in the code"

    public function postLogin(Request $request)
    {
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);

        // 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.
        $throttles = $this->isUsingThrottlesLoginsTrait();

        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);

        /*
        * Here I will need to store the following info in a table
        *   - Username
        *   - User IP address
        *   - Total Attempts so far
        *
        * Additionally, I will need to override the Auth::attempt method
        * to check another a table for trusted IP access list and check the time range "if applicable"
        * 
        *
        */
        
        
        if (Auth::attempt($credentials, $request->has('remember'))) {
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

        // 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.
        if ($throttles) {
            $this->incrementLoginAttempts($request);
        }

        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }
accent-interactive's avatar

You do not need to override the trait itself. Simply create a public function getLogin() in your AuthController and do the stuff that you wish tot do there.

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Validator;

class AuthController extends Controller
{
    
    use AuthenticatesAndRegistersUsers, ThrottlesLogins;

    public function __construct()
    {
        $this->middleware('guest', ['except' => 'getLogout']);
    }

    public function getLogin(){
        // Do your custom login magic here.
    }

}

2 likes
bimalshah72's avatar

@malhayek

trait's method never be overrided, means trait methods are simplicity to include method in your class.

Laravel has provided out of the box, authentication module, hence I think we should not disturb that, unless really required.

Also you shouldn't / couldn't override Auth::attempt also, since this method is framework method log laravel in Illuminate\Auth\Guard

Best approach would be .. instead of getLogin, postLogin etc in your AuthController ..I think, there is once more method which would be called after successfullt authenticated ... handleUserWasAuthenticated in AuthenticateUser trait, this method you should write in AuthController...

protected function handleUserWasAuthenticated(Request $request, $throttles)
    {
            
    /*
        * Once this is ok then you have to store the following info in a table
        *   - Username
        *   - User IP address
        *   - Total Attempts so far          *
        */
    if ($throttles) {
            $this->clearLoginAttempts($request);
        }

        if (method_exists($this, 'authenticated')) {
            return $this->authenticated($request, Auth::user());
        }

        return redirect()->intended($this->redirectPath());
    }

regarding - ip checking and other stuff


To check another a table for trusted IP access list and check the time range "if applicable" - if false, return 
        redirect() back with friendly message ... for this you can also implement middleware - attach this middleware for getLogin and          postLogin

2 likes
randm's avatar

Thanks a lot @joostvanveen I was able to override it to capture every login attempt.

@bimalshah72 , I am trying to log every "successful or failed" attempt in a database along with other info.

Also, if the username/password combo is correct, then I want to do couple other check before the session is created

  1. Check to make sure the IP is trusted
  2. Check make sure the login time is with in the allowed time frame.

Note: the 2 steps listed above will have to take place before the session is created. If the user did not meet any of the 2 methods above, then the session will NOT be created. and a new message should be returned to the user

To avoid changing the built in class using override, then: How would I add a middleware to be executed before the session is created? How could I add another middleware to be executed on every attempt just after the attempt is incremented?

Without knowing how to implement the second middleware "above" the only other way I would think implementing/overriding the method validateCredentials inside the UserProvider will allow me to do extra checks before it returns true. "it is found in Illuminate\Contracts\Auth\UserProvider.php;"

    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  array  $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, array $credentials);

Thank you

FYI, This is how I overrode the postLogin method

    public function postLogin(Request $request)
    {

        //dd( $this->getCredentials($request) );
        $authenticated = false;

        $this->validate($request, [
            $this->loginUsername() => 'required',
            'password' => 'required'
        ]);

        // 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.
        $throttles = $this->isUsingThrottlesLoginsTrait();


        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);

        
        if (Auth::attempt($credentials, $request->has('remember'))) {
            $authenticated = true;
        }
        
        $this->saveAttemptRecord($request, $authenticated);

        if($authenticated){
            return $this->handleUserWasAuthenticated($request, $throttles);
        }

        // 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.
        if ($throttles) {
            $this->incrementLoginAttempts($request);
        }

        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }


    /**
     * Store the login attempt in the database
     *
     * @param  Request $request
     * @param  Boolean $authenticated
     * @return void
     */
    private function saveAttemptRecord(Request $request, $authenticated)
    {
            
        $log = new ThrottleLog;
        $log->username = $this->getUserName($request);
        $log->attempts = $this->getLoginAttempts($request);
        $log->ip_address = ip2long( $request->ip() );
        $log->user_agent = $request->header('User-Agent') !== null ? $request->header('User-Agent') : '';
        $log->result = $authenticated ? 'Pass' : 'Fail';

        $log->save();

    }

    /**
     * Get the userName that is attempting to login
     *
     * @param  Request $request
     * @return string username
     */
    private function getUserName(Request $request)
    {
        return isset($request->only($this->loginUsername())[$this->loginUsername()]) ? $request->only($this->loginUsername())[$this->loginUsername()] : '';
    }
jaydeluca's avatar

There doesn't seem to be an AuthController in 5.3, does anyone know how I would go about editing the login methods without having to directly edit Illuminate\Foundation\Auth\AuthenticatesUsers ?

If i write a new login() method in LoginController.php will it use that instead of the default one in AuthenticatesUsers?

Snapey's avatar

@jaydeluca

Look inapp/Http/Controllers/Auth/LoginController.php

In there you will find use AuthenticatesUsers which is a trait

Any methods you want to override, copy the trait to your LoginController and edit there.

ps. next time, start your own thread

8 likes

Please or to participate in this conversation.