34

I'm currently working on my Laravel app and to prevent spam I decided that only active users are able to login. I'm currently using Laravel's login system just like in Laravel's official website tutorial, here's my form action:

<form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/login') }}">

This works completely fine, however I'd like to check the user's active, if not active it would be redirected to the activation page, otherwise it would login. Is there a simple way to do this or am I obligated to make a new controller, routes and more verifications? Thank you.

Edit: Forgot to mention that I have a 'active' column in my database.

BrokenBinary
  • 7,731
  • 3
  • 43
  • 54
Micael Sousa
  • 1,129
  • 3
  • 10
  • 16

23 Answers23

74

Laravel 5.4 / 5.5

Override the default login() function by placing this function in your LoginController:

public function login(\Illuminate\Http\Request $request) {
    $this->validateLogin($request);

    // 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 ($this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);
        return $this->sendLockoutResponse($request);
    }

    // This section is the only change
    if ($this->guard()->validate($this->credentials($request))) {
        $user = $this->guard()->getLastAttempted();

        // Make sure the user is active
        if ($user->active && $this->attemptLogin($request)) {
            // Send the normal successful login response
            return $this->sendLoginResponse($request);
        } else {
            // Increment the failed login attempts and redirect back to the
            // login form with an error message.
            $this->incrementLoginAttempts($request);
            return redirect()
                ->back()
                ->withInput($request->only($this->username(), 'remember'))
                ->withErrors(['active' => 'You must be active to login.']);
        }
    }

    // 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 $this->sendFailedLoginResponse($request);
}

Overriding the login() method in this way is recommended over many of the other answers on this question because it allows you to still use many of the more advanced authentication functionality of Laravel 5.4+ such as login throttling, multiple authentication guard drivers/providers, etc. while still allowing you to set a custom error message.


Laravel 5.3

Change or override your postLogin() function in your AuthController to look like this:

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

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

    // This section is the only change
    if (Auth::validate($credentials)) {
        $user = Auth::getLastAttempted();
        if ($user->active) {
            Auth::login($user, $request->has('remember'));
            return redirect()->intended($this->redirectPath());
        } else {
            return redirect($this->loginPath()) // Change this to redirect elsewhere
                ->withInput($request->only('email', 'remember'))
                ->withErrors([
                    'active' => 'You must be active to login.'
                ]);
        }
    }

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

}

This code redirects back to the login page with an error message about the user being inactive. If you want to redirect to an authentication page you would change the line I marked with the comment Change this to redirect elsewhere.

BrokenBinary
  • 7,731
  • 3
  • 43
  • 54
  • 1
    Thanks, it works. I use tha for error message: ->withErrors([$this->username() => 'You must be active to login.']); – jpussacq Feb 16 '18 at 13:40
  • 3
    One should note that if one has used `make:auth` and made the changes mentioned here, then an inactive user may still login through the password reset function. This can be prevented as explained in https://stackoverflow.com/a/52652821/2311074 – Adam Oct 04 '18 at 18:04
  • why dont we use middleware here , since banning action from admin may happen at any time, even during the time the user is browsing the site, being already logged in. Or they may choose “Remember me” and never have to log in at all. – Rohit Kumar Jan 29 '20 at 08:42
  • moreover , if you have any idea , to achieve this in laravel 6 – Rohit Kumar Jan 29 '20 at 08:42
  • 1
    @RohitKumar Instead of using a middleware that runs on every request, it would be better to just log out the user by invalidating their session when you ban them. – BrokenBinary Feb 10 '20 at 18:50
55

In Laravel 5.4 open Auth/LoginController.php

and add this function:

/**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(\Illuminate\Http\Request $request)
    {
        //return $request->only($this->username(), 'password');
        return ['email' => $request->{$this->username()}, 'password' => $request->password, 'status' => 1];
    }

And you are done..!

Raja Amer Khan
  • 1,489
  • 10
  • 31
  • 2
    This makes sense do a degree, however note that you cannot set a custom message this way. it will validate against and return a generic can't login error. However if you want a custom message such as 'Account not active', follow [This answer](https://stackoverflow.com/a/31016210/3604087) – Ian May 24 '17 at 09:31
  • How do add condition to this ? Support I want to allow users with role 1 and 2. – Samay Jun 06 '17 at 11:01
  • @Samay You need to add that check through middleware in your routes. – Raja Amer Khan Jul 29 '17 at 11:08
25

Paste the following method to your LoginController.

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'exists:users,' . $this->username() . ',active,1',
        'password' => 'required|string',
    ]);
}

The last two comma-separated parameters (active,1) act as a WHERE clause (WHERE active = '1') and can be alternatively written this way:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => Rule::exists('users')->where(function ($query) {
            $query->where('active', 1);
        }),
        'password' => 'required|string'
    ]);
}

Normally, the validation method only checks if email and password fields are filled out. With the modification above we require that a given email address is found in a DB row with active value set to 1.

You can also customize the message:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'exists:users,' . $this->username() . ',active,1',
        'password' => 'required|string',
    ], [
        $this->username() . '.exists' => 'The selected email is invalid or the account has been disabled.'
    ]);
}

Note that the above message will be shown both when a given email address doesn't exist or when the account is disabled.

Mateusz
  • 2,340
  • 25
  • 24
  • This makes sense but how do we have a custom error message ? – Samay Dec 14 '16 at 13:56
  • If you're okay with one message for both cases (1) when a given email address doesn't exist or (2) when the account is disabled, you can use the code above under UPDATE. – Mateusz Dec 15 '16 at 18:13
  • I've tested the code under UPDATE using `Laravel v5.5.20` - it's still working great! It's my favourite solution. It's short, simple and it does, what it should do. – checker284 Nov 11 '17 at 20:37
  • This seems a cleaner and safer solution than the accepted answer which overrides the entire login() method. I think the long form using Rule::exists() methods is clearer than the shorthand which is somewhat undocumented. – BlueC Nov 02 '18 at 11:04
  • this is an elegant and simple solution, I don't have to install any unnecessary package, two thumbs up, you saved my day! – Budianto IP Jan 20 '20 at 07:32
  • The other answer of overriding the `login` method would need to be edited for Laravel 8 as it has changed, but this is much simpler and still works great :) – Chris Aug 06 '21 at 21:39
15

On laravel 7, you only need to put this method on LoginController:

/**
 * Custom credentials to validate the status of user.
 */
public function credentials(Request $request)
{
    return [
        'email'     => $request->email,
        'password'  => $request->password,
        'is_active' => '1'
    ];
}

In this way, you can validate any condition for login.

albert
  • 1,766
  • 1
  • 21
  • 24
7

in AuthController override method getCredentials like this:

protected function getCredentials(Request $request) {

        $request['active'] = TRUE;
        return $request->only($this->loginUsername(), 'password', 'active');
}

make sure you have the column active on user table...

pls13
  • 71
  • 1
  • 1
  • 4
    This is simple and short answer, the only issue with it is that with this method, you cant customize the error message when not active. or is there a way you can customize the error message when not active? – Toni Jul 11 '16 at 12:45
4

You don't have to override the whole function. You can just change the Validator in AuthController to achieve that adding "exists:table,column" validation.

Let's assume that you have a users table with email,password and active fields.

'email' => 'exists:users,email,active,1'

Here is the validotor function should look like in AuthController.php

protected function validator(array $data)
{
    return Validator::make($data, [
        'email' => 'required|email|max:255|exists:users,email,active,1',
        'password' => 'required|confirmed'
    ]);
}

or if you are using soft deletes this should work too.

'email' => 'exists:users,email,deleted_at,NULL'

You can also check out the validation rule at this link http://laravel.com/docs/5.1/validation#rule-exists

Can Celik
  • 2,050
  • 21
  • 30
  • 2
    I think these validation rules only applies at registration step. According to docBlock before `validator` function in `AuthController.php`: **Get a validator for an incoming registration request.** – mrdaliri Aug 28 '15 at 16:56
4

Laravel 5.8 tested. Put this code in your LoginController.php and be happy.

public function login(Request $request)
{
    $user = User::where('username',$request->username)->first();
    if( $user && !$user->active){
        return redirect()->back()->with('error','the user has been desactivated');
    }

    $this->validateLogin($request);

    // 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 ($this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);

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

    if ($this->attemptLogin($request)) {
        return $this->sendLoginResponse($request);
    }

    // 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 $this->sendFailedLoginResponse($request);
}
thiago tanaka
  • 808
  • 8
  • 8
4

Laravel 6.6 tested. Overwrite validateLogin in your LoginController.php

use Illuminate\Http\Request;
use App\User;
use Illuminate\Validation\ValidationException;

......

/**
 * Validate the user login request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 *
 * @throws \Illuminate\Validation\ValidationException
 */
protected function validateLogin(Request $request)
{
    // Get the user details from database and check if user is exist and active.
    $user = User::where('email',$request->email)->first();
    if( $user && !$user->activation){
        throw ValidationException::withMessages([$this->username() => __('User has been desactivated.')]);
    }

    // Then, validate input.
    return $request->validate([
        $this->username() => 'required|string',
        'password' => 'required|string',
    ]);
}
basak
  • 51
  • 3
3

Works on Laravel 7

I know this has already been answered many times but here was my approach and it isn't much different from some of the others but I wanted to provide a little more detailed explanation for some of the choices I made.

I decided for my app that it was ok to simply abort 403 if the user is not active, returning validation exceptions has already been fairly covered here.

My suggestion here is to override the login method from vendor/laravel/ui/auth-backend/AuthenticatesUsers.php by copying it into app/Http/Controllers/Auth/LoginController.php. I would also suggest adding this check after the throttle check as that should take precedent imo.

Here's what my LoginController looks like. Just pulling in the login method and added about 3-4 lines of code.

use AuthenticatesUsers;

/**
 * Where to redirect users after login.
 *
 * @var string
 */
protected $redirectTo = RouteServiceProvider::HOME;

/**
 * Create a new controller instance.
 *
 * @return void
 */
public function __construct()
{
    $this->middleware('guest')->except('logout');
}

/**
 * Handle a login request to the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
 *
 * @throws \Illuminate\Validation\ValidationException
 */
public function login(Request $request)
{
    $this->validateLogin($request);

    // 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);
    }

    // Check if user is active
    $user = User::where('email', $request->email)->first();
    if ($user && !$user->active) {
        abort(403, 'Your account has been disabled by an administrator.');
    }

    if ($this->attemptLogin($request)) {
        return $this->sendLoginResponse($request);
    }

    // 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 $this->sendFailedLoginResponse($request);
}
fylzero
  • 460
  • 6
  • 18
3

Works on Laravel 7

Note that you should also add the 'is_active' check in the ForgotPasswordController. Otherwise the user will be able to login by requesting a new password without the 'is_active' flag is verified

class ForgotPasswordController extends Controller
{
    //...

    protected function credentials(Request $request)
    {
        // is_active field in user model must be true.
        $request->merge(['is_active' => true]);

        return $request->only('email', 'is_active');
    }
}
kluver
  • 396
  • 4
  • 7
3

LARAVEL 8
I have a column in User Table with value 1 and 0. Here 1 is Active and 0 is Inactive.
Add these lines in

/vendor/laravel/ui/auth-backend/AuthenticatesUsers.php

    public function login(Request $request)
{
    $this->validateLogin($request);

    // 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);
    }

  //ADD THIS SECTION ONLY
  //SECTION STARTS
  // CHECK IF USER EXISTS IN OUR USER TABLE.
  if ($this->guard()->validate($this->credentials($request))) {
    //IF USER EXISTS, FIND USER USING EMAIL FROM REQUEST
    $user = User::where('email', $request->email)->first();
    //CHECK STATUS OF USER (HERE, 1 = ACTIVE & 0 = INACTIVE)
    if ($user->status===0) {
        //THROW ERROR WITH CUSTOM MESSAGE
        throw ValidationException::withMessages([$this->username() => __('User account has been deactivated.')]);
    }
  }
  //SECTION ENDS

    if ($this->attemptLogin($request)) {
        return $this->sendLoginResponse($request);
    }

    // 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 $this->sendFailedLoginResponse($request);
}
Bikalpa
  • 98
  • 5
  • if you use AuthenticatesUsers trait in a LoginController you simply override login function and write this code in it. – muratGursel Jan 07 '22 at 21:58
2

In case anyone is came here looking for information on Laravel 5.4/5.5, and that allows for a custom message just for this scenario (not a combined message) here's the answer for that from https://laracasts.com/discuss/channels/laravel/user-account-status

Override the 'authenticated' method within your'app/Http/Controllers/Auth/LoginController.php` file:

/**
 * The user has been authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
protected function authenticated(Request $request, $user)
{
    if ($user->status_id == 2) { // or whatever status column name and value indicates a blocked user

        $message = 'Some message about status';

        // Log the user out.
        $this->logout($request);

        // Return them to the log in form.
        return redirect()->back()
            ->withInput($request->only($this->username(), 'remember'))
            ->withErrors([
                // This is where we are providing the error message.
                $this->username() => $message,
            ]);
    }
}
Jeremy L.
  • 853
  • 8
  • 15
  • This `authenticated()` method is called after the login attempts count has been cleared, meaning that you can't use this to trigger a failed login attempt with login throttling. – BrokenBinary Dec 01 '17 at 20:35
  • Thanks @BrokenBinary, and thanks for the update for 5.4. – Jeremy L. Dec 07 '17 at 18:48
2

I check user is actived by overwrite sendLoginResponse function in LoginController

protected function sendLoginResponse(Request $request)
{
    if($this->guard()->user()->active == 0){
        $this->guard()->logout();
        return redirect()->back()
            ->withInput($request->only($this->username(), 'remember'))
            ->withErrors(['active' => 'User in not activated.']);
    }

    $request->session()->regenerate();

    $this->clearLoginAttempts($request);

    return $this->authenticated($request, $this->guard()->user())
            ?: redirect()->intended($this->redirectPath());
}
Mohsen
  • 4,049
  • 1
  • 31
  • 31
2

If someone uses ajax request on login and wants to have custom message, here is how I achieved this in login controller:

login() function

  // This section is the only change
    if ($this->guard()->validate($this->credentials($request))) {
        $user = $this->guard()->getLastAttempted();

        // Make sure the user is active
        if ($user->status == 1 && $this->attemptLogin($request)) {
            // Send the normal successful login response
            return $this->sendLoginResponse($request);
        } else {
            // Increment the failed login attempts and redirect back to the
            // login form with an error message.
            $this->incrementLoginAttempts($request);
            return $this->sendFailedLoginResponse($request, true);
        }
    }

And other functions

 public function sendLoginResponse(Request $request)
{
    $redirectTo = false;
    if ($request->headers->get('referer') == env('APP_URL') . '/' || $request->headers->get('referer') == env('APP_URL') . '/login') {
        $redirectTo = $this->redirectPath();
    }

    if ($request->expectsJson()) {
        return response()->json(['status' => true, 'user' => auth()->user(), 'redirectTo' => $redirectTo, 'fragments' => [
            '#main-nav' => view('includes.nav')->render()
        ]]);
    } else {
        return redirect($redirectTo);
    }
}

public function sendFailedLoginResponse(Request $request, $user_not_active = fasle)
{
    if ($user_not_active) {
        return response()->json(['status' => false, 'email' => 'Your account is not active.']);
    }
    return response()->json(['status' => false, 'email' => 'Incorrect login credentials.']);
}
2

Thanks @Can_Celik

this was how I was able to solve my issue becos i was using json response with jquery.

/**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function validateLogin(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email|exists:users_table,email,account_status_colunm,active_value',
            'password' => 'required',
        ]);
    }

then in the validation.php file add this to your Custom Validation strings

...
'email' => [
        'exists' => 'Account has been disabled. Contact our team.'
    ],

that's about all...works fine ...

The Billionaire Guy
  • 3,382
  • 28
  • 31
2

I'm new to Laravel, and this is aimed at newcomers too. Long-timers feel free to tell me why this is bad practice, as I genuinely don't know any better yet.

As at 24th August 2019 - using Laravel 5.8 - This is my personal implementation.

Assumptions made:

  1. You started out using Artisan Make:Auth
  2. You've added 'active' as a bool (tinyInt) to your User table and updated the relevant Models etc...
  3. You're trying to prevent users from gaining access to your application via standard Auth, when: 'active' = 0.

If this is the case, you can leave your LoginController alone.

Instead open "Illuminate/Auth/Middleware/Authenticate.php" and replace the handle() method with:

public function handle($request, Closure $next, ...$guards)
    {
        if(!$request->user()->active){
            // either abort with simple 403 access denied page
            // abort(403, "You don't have permissions to access this area");

            // OR force Logout and redirect back to the login page
            return redirect('login')->with($this->auth->logout());
        }

        $this->authenticate($request, $guards);
        return $next($request);
    }

Note: Auth::logout() won't work here, but it's already pulled in via the constructor at the top of the file.

public function __construct(Auth $auth)
    {
        $this->auth = $auth;
    }

So you can just use $this->auth->logout(); instead.

Thinking about it - You could very easily swap 'Active' for pretty much any criteria and update this middleware the very same way! Hope this helps!

Ryan Tirrell
  • 63
  • 1
  • 8
2

Most logical, and clean, is to handle this within the validateLogin method.

LoginController.php (Laravel 6.x)

/**
 * Validate the user login request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 *
 * @throws \Illuminate\Validation\ValidationException
 */
protected function validateLogin(Request $request)
{
    // Get the user details from database and check if email is verified.
    $user = User::where('username', '=', $request->input($this->username()))->first();
    if ($user->email_verified_at == NULL) {
        throw ValidationException::withMessages([$this->username() => __('auth.failed_login_missing_email_verification')]);
    }

    // Email is verified, validate input.
    return $request->validate([
        $this->username() => 'required|string',
        'password' => 'required|string',
    ]);
}
PatricNox
  • 3,306
  • 1
  • 17
  • 25
2

With Laravel Fortify makes it much cleaner to Customizing User Authentication

E.g addded status to the user condition in the FortifyServiceProvider

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;
 
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Fortify::authenticateUsing(function (Request $request) {
        $user = User::where('email', $request->email)->where('status', 1)->first();
 
        if ($user &&
            Hash::check($request->password, $user->password)) {
            return $user;
        }
    });
 
    // ...
}
John Magnolia
  • 16,769
  • 36
  • 159
  • 270
1

You can use Eloquent scopes: https://laravel.com/docs/5.5/eloquent#query-scopes

like this:

class User extends Authenticatable {
...
/**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot() {
        parent::boot();

        static::addGlobalScope('scopeActive', function (Builder $builder) {
            $builder->where('active', 1);
        });
    }
...
1

In case, you want to keep everything as simple, you can use Laravel built-in feature. It is email verification. I do not guarantee this way would resolve your problem. It is reference in case you didn't know about it before.

Follow the doc at https://laravel.com/docs/7.x/verification, all you have to do are a few steps.

  1. Implementation of the User model with MustVerifyEmail
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;

    // ...
}
  1. Active the middleware verify for the routes in web.php or in controller

  2. You can activate the verification link and verify email

Auth::routes(['verify' => true]);
  1. Make sure the user migration has included email_verified_at column.

I often use this built-in feature if I need verification users before allowing it to access the application.

Duy Nguyen
  • 334
  • 4
  • 10
1

Probably not the best but, I think I found a cleaner way to override the login method. I tried this on Laravel 7

in Auth\LoginController.php, put these classes

use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

and then, add(override) these functions inside LoginController class:

public function login(Request $request){        
    $this->validateLogin($request);

    if (method_exists($this, 'hasTooManyLoginAttempts') &&
        $this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);

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

    if($this->guard()->validate($this->credentials($request))) {
        // Check if user is active, else return error message
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password, 'status' => 'A'])) {
            return redirect()->intended('dashboard');
        }  else {
            // This will return the message required as desired
            return $this->inactiveCredential($request);
        }
    } else {            
        $this->incrementLoginAttempts($request);
        return $this->sendFailedLoginResponse($request);
    }
}

// Error massage for inactive credential
private function inactiveCredential(Request $request){    
    throw ValidationException::withMessages([
        // auth.not-active can be added in resources/lang/en/auth.php
        $this->username() => [trans('auth.not-active')],
    ]);    
}

Then add this line in resources/lang/en/auth.php. If there are more than 1 language, you should put this line in there too.

'not-active' => 'This account is already deleted. Contact administrator to revoke this account',

Then you should have this response on the default laravel-ui login interface Login Credential

sk8gear
  • 11
  • 2
1
  protected function sendLoginResponse(Request $request) {
  $request->session()->regenerate();
  $this->clearLoginAttempts($request);
  if ($response = $this->authenticated($request, $this->guard()->user())) {
      return $response;
  }
  $user = $this->guard()->user();
  if($user->is_active) {
    return $request->wantsJson() ? new JsonResponse([], 204) : redirect()->intended($this->redirectPath());
  } else {
    $request->session()->flush();
    return redirect()->route('login')->with('error', 'This account is not activated. Please contact the administrator.');
  }    
}

I put this function inside Auth\LoginController

Dharman
  • 30,962
  • 25
  • 85
  • 135
Rashi Goyal
  • 933
  • 9
  • 15
1

I needed mine to be combined with the Eloquent provider since we are not using the standard User model / table.

In auth.php

    'providers' => [
        'custom' => [
            'driver' => 'active-user-provider',
            'model' => App\CustomModel::class,
        ]
    ]
    'guards' => [
       'web' => [
            'driver' => 'session',
            'provider' => 'custom'
      ]
],
'passwords' => [
   'custom' => [
        'provider' => 'custom',
        ....
    ]
]

In App\Extensions\ActiveUserProvider

class ActiveUserProvider extends EloquentUserProvider
{
    /**
     * Get a new query builder for the model instance.
     *
     * @param \Illuminate\Database\Eloquent\Model|null $model
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function newModelQuery($model = null)
    {
        return parent::newModelQuery($model)
            ->where('active', true);
    }
}

In AuthServiceProvider

Auth::provider('active-user-provider', fn($app, array $config) => 
   new ActiveUserProvider($app['hash'], $config['model'])
);

This way it also only sends password reset emails to active workers.

Healyhatman
  • 1,482
  • 1
  • 14
  • 23