Laravel: How To disable Login for a deactivated user?

...In the Laravel way

There are cases where you just need to "Deactivate" (Not delete) the user. The use case may also be to block access temporarily for someone.

Initial steps

Add a column in the user table where you can manage the user activation status. Keeping the column name is_active as of now.

php artisan make:migration add_is_active_to_users_table

Add the column in migration file's up() and down() functions as required.

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->boolean('is_active')->default(1);
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('is_active');
    });
}

Run the migration

php artisan migrate

Authenticating user

To check if the user is active along with their credentials, Check out the Laravel documentation to manually authenticate the users and simply add the required column's information in the $credentials variable in the authenticate() function of LoginController.php

$credentials = $request->validate([
    'email' => ['required', 'email'],
    'password' => ['required'],
]);

$credentials['is_active'] = 1;

That's it! You're done! The user will not be able to login into the application if their is_active value is false/0.

But, What about the Middleware way?

When I was implementing this functionality, I found several blogs online which suggest creating the Middleware and checking your user there (Like this and this). But I found a flaw in this approach.

The flow goes like this:

  1. The deactivated user tries to log in

  2. The user gets authenticated successfully,

  3. The request goes to the Middleware.

  4. Middleware checks if the user is deactivated

  5. Middleware finds the user as deactivated, it logs out the user

In this flow, the Illuminate\Auth\Events\Authenticated event will still get triggered as the deactivated/blocked user tries to log in. This should not be the case. The event that should be triggered is Illuminate\Auth\Events\Failed .

The catch:

If you follow the Laravel way, it will simply show the user a generic message same as when the credentials don't match as per our records. But in the middleware example, you can inform the user that you've been blocked.

So, should we follow the middleware approach if we want to notify the user that you're blocked?

I would still not recommend it as this flow is not as per how the Authentication works. We have to use the attemptWhen functionality for additional conditions and setting up custom flash messages if required. Please check Laravel's documentation here for more details. This functionality with examples may be covered later in another blog.