Search code examples
phplaravellaravel-middleware

Override default Laravel EnsureEmailIsVerified middleware not firing


I am building a rest api using Laravel 8. I want to override the default EnsureEmailisVerified middleware and move the code I have from the controller into that middleware.

The code I have in my login controller for checking if the email is verified is;

if (!$user->hasVerifiedEmail()) {
    return response()->json([
        'message' => 'You need to confirm your account. We have sent you an activation link to your email.'
    ], 422);
}

This works great, but I want to move this out of the controller, So I created a middleware and moved the code into it as follows;

class EnsureEmailIsVerified
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next): mixed
    {
        if (! $request->user() ||
            ($request->user() instanceof MustVerifyEmail &&
                ! $request->user()->hasVerifiedEmail())) {
            return response()->json([
                'message' => 'You need to confirm your account. We have sent you an activation link to your email.'
            ], 422);
        }

        return $next($request);
    }
}

Then in my Kernel.php file I added;

'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class,

and then my login route looks like so;

Route::post('login', [Auth\AuthenticationController::class, 'login'])->middleware('verified');

The problem is that it is not firing at all ... When I hit the login route it doesn't seem to check if the email is verified and just logs the user in.


Solution

  • You have set middleware to run before the authentication route runs. However the authentication route is where the user is logged in. At the point the middleware runs, the authentication has not happened yet. You need to switch your middleware to one that runs after the main controller request:

    class EnsureEmailIsVerified
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle(Request $request, Closure $next): mixed
        {
            $response = $next($request);
            // $request->user() may also work
            if (auth()->check() &&
                (auth()->user() instanceof MustVerifyEmail &&
                    !auth()->user()->hasVerifiedEmail())) {
                    auth()->logout();
                return response()->json([
                    'message' => 'You need to confirm your account. We have sent you an activation link to your email.'
                ], 422);
            }
            return $response;
    
        }
    }