Notify Locked Out Users in Laravel

Laravel offers a nice feature, that locks out the users that attempted to login too much. It’s a nice way to prevent brute force logins. But how can we notify the user, when the lockout happens? Maybe it wasn’t the user who attempted to log in.

Setting Up the Listener for the Lockout Event

When a user’s email address is used for 5 or more times for login and the attempts were failed, the framework locks out the email address for 60 seconds. In some cases, we may want to notify the user about the lockout.

When the lockout happens Laravel fires an Illuminte\Auth\Events\Lockout event. As we know, we can easily set up a listener for this event and handle any logic we want. Let’s make the listener with the php artisan make:listener UserLockedOut command. Then bind the listener to the event in the event service provider.

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    ...
    \Illuminate\Auth\Events\Lockout::class => [
        \App\Listeners\UserLockedOut::class,
    ],
    ...
];

Making the Notification

So, before we move on the listener itself, let’s create the notification we send to the user. With Laravel, we can easily handle user-level notifications in various forms. For us, the default email-based notification is perfect. Let’s generate the notification class by running the php artisan make:notification LockedOut command.

After we’re done, we can customize the message of the email. We keep it simple here, but of course, you can make it as you wish – the possibilities are endless.

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class LockedOut extends Notification
{
    use Queueable;

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('This email has been locked out temporary.')
                    ->line('There was too many login attempts with this email address!');
    }
}
By default, the channel is mail, If you need a different channel, you can take a look at the documentation to discover your possibilities.

Notify the User

Now, we can notify the user in the listener’s handle method. Whenever the event will be fired, the handle method is automatically called with the event object passed as a parameter.

<?php

namespace App\Listeners;

use App\User;
use App\Notifications\LockedOut;
use Illuminate\Auth\Events\Lockout;

class UserLockedOut
{
    /**
     * Handle the event.
     *
     * @param  \Illuminate\Auth\Events\Lockout  $event
     * @return void
     */
    public function handle(Lockout $event)
    {
        if ($user = User::where('email', $event->request->email)->first()) {
            $user->notify(new LockedOut);
        }
    }
}

As we see, we check if the user exists, then we notify it with the previously generated notification class. From now, anytime a user locked out itself, it should get an email with the content we set up.

Special thanks for the following recource(s): Icon made by Freepik from www.flaticon.com
Need a web developer? Maybe we can help, get in touch!