title: Laravel Users can login despite they are not verified
body: <p>I am working in a SPA with Laravel sanctum, The frontend was made with Reacts, The client wants that users can verify their emails before they can login. So I made this changes:</p>
  <p>Models/User.php</p>
  <pre><code>&lt;?php
  
  namespace App\Models;
  
  use Illuminate\Contracts\Auth\MustVerifyEmail;
  use Illuminate\Database\Eloquent\Factories\HasFactory;
  use Illuminate\Foundation\Auth\User as Authenticatable;
  use Illuminate\Notifications\Notifiable;
  use Laravel\Sanctum\HasApiTokens;
  use App\Notifications\VerifyEmail;
  
  class User extends Authenticatable implements MustVerifyEmail
  {
      use HasFactory, Notifiable, HasApiTokens;
  
      .....        
      
      public function sendEmailVerificationNotification()
      {                
          $this-&gt;notify(new VerifyEmail());
      }
  }
  </code></pre>
  <p>composer.js</p>
  <pre><code>....
  &quot;require&quot;: {
          &quot;php&quot;: &quot;^7.3|^8.0&quot;,
          &quot;babenkoivan/elastic-migrations&quot;: &quot;^1.5&quot;,
          &quot;fideloper/proxy&quot;: &quot;^4.4&quot;,
          &quot;fruitcake/laravel-cors&quot;: &quot;^2.0&quot;,
          &quot;guzzlehttp/guzzle&quot;: &quot;^7.0.1&quot;,
          &quot;laravel/framework&quot;: &quot;^8.12&quot;,
          &quot;laravel/sanctum&quot;: &quot;^2.9&quot;,
          &quot;laravel/tinker&quot;: &quot;^2.5&quot;
      },
      &quot;require-dev&quot;: {
          &quot;facade/ignition&quot;: &quot;^2.5&quot;,
          &quot;fakerphp/faker&quot;: &quot;^1.9.1&quot;,
          &quot;laravel/breeze&quot;: &quot;^1.0&quot;,
          &quot;laravel/sail&quot;: &quot;^1.0.1&quot;,
          &quot;mockery/mockery&quot;: &quot;^1.4.2&quot;,
          &quot;nunomaduro/collision&quot;: &quot;^5.0&quot;,
          &quot;phpunit/phpunit&quot;: &quot;^9.3.3&quot;
      }
  ....
  </code></pre>
  <p>routes/auth.php</p>
  <pre><code>&lt;?php
  
  use App\Http\Controllers\Auth\AuthenticatedSessionController;
  use App\Http\Controllers\Auth\ConfirmablePasswordController;
  use App\Http\Controllers\Auth\EmailVerificationNotificationController;
  use App\Http\Controllers\Auth\EmailVerificationPromptController;
  use App\Http\Controllers\Auth\NewPasswordController;
  use App\Http\Controllers\Auth\PasswordResetLinkController;
  use App\Http\Controllers\Auth\RegisteredUserController;
  use App\Http\Controllers\Auth\VerifyEmailController;
  use Illuminate\Support\Facades\Route;
  
  
  Route::post('/register', [RegisteredUserController::class, 'store'])
                  -&gt;middleware('guest');
  
  Route::get('/login', [AuthenticatedSessionController::class, 'create'])
                  -&gt;middleware('guest')
                  -&gt;name('login');
  
  Route::post('/login', [AuthenticatedSessionController::class, 'store'])
                  -&gt;middleware(['guest']);
  
  Route::get('/forgot-password', [PasswordResetLinkController::class, 'create'])
                  -&gt;middleware('guest')
                  -&gt;name('password.request');
  
  Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])
                  -&gt;middleware('guest')
                  -&gt;name('password.email');
  
  Route::get('/reset-password/{token}', [NewPasswordController::class, 'create'])
                  -&gt;middleware('guest')
                  -&gt;name('password.reset');
  
  Route::post('/reset-password', [NewPasswordController::class, 'store'])
                  -&gt;middleware('guest')
                  -&gt;name('password.update');
  
  Route::get('/verify-email', [EmailVerificationPromptController::class, '__invoke'])
                  -&gt;middleware('auth')
                  -&gt;name('verification.notice');
  
  /*Route::get('/verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
                  -&gt;middleware(['auth', 'signed', 'throttle:6,1'])
                  -&gt;name('verification.verify');*/
  
  Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
                  -&gt;middleware(['auth', 'throttle:6,1'])
                  -&gt;name('verification.send');
  
  Route::get('/confirm-password', [ConfirmablePasswordController::class, 'show'])
                  -&gt;middleware('auth')
                  -&gt;name('password.confirm');
  
  Route::post('/confirm-password', [ConfirmablePasswordController::class, 'store'])
                  -&gt;middleware('auth');
  
  Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
                  -&gt;middleware('auth')
                  -&gt;name('logout');
  </code></pre>
  <p>routes/api.php</p>
  <pre><code>&lt;?php
  
  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Route;
  use \App\Models\User;
  use \App\Http\Controllers\TweetsController;
  use App\Http\Controllers\Auth\VerifyEmailController;
  
  Route::middleware(['auth:sanctum'])-&gt;get('/user', function (Request $request) {
      return $request-&gt;user();
  });
  
  Route::middleware(['auth:sanctum'])-&gt;group(function () {
      
      Route::get('/posts',[PostsController::class,'index']);
      Route::post('/posts',[PostsController::class, 'store']);
      Route::get('/verify-email/{hash}', [VerifyEmailController::class, 'verify'])
                  -&gt;middleware(['throttle:6,1'])
                  -&gt;name('verification.verify');               
  
  });
  </code></pre>
  <p>routes/web.php</p>
  <pre><code>&lt;?php
  
  use Illuminate\Support\Facades\Route;
  
  /*
  |--------------------------------------------------------------------------
  | Web Routes
  |--------------------------------------------------------------------------
  |
  | Here is where you can register web routes for your application. These
  | routes are loaded by the RouteServiceProvider within a group which
  | contains the &quot;web&quot; middleware group. Now create something great!
  |
  */
  
  Route::get('/', function () {
      return view('welcome');
  });
  
  Route::get('/dashboard', function () {
      return view('dashboard');
  })-&gt;middleware(['auth'])-&gt;name('dashboard');
  
  require __DIR__.'/auth.php';
  </code></pre>
  <p>app\Http\Controllers\Auth\VerifyEmailController.php</p>
  <pre><code>&lt;?php
  
  namespace App\Http\Controllers\Auth;
  
  use App\Http\Controllers\Controller;
  use App\Providers\RouteServiceProvider;
  use Illuminate\Auth\Events\Verified;
  //use Illuminate\Foundation\Auth\EmailVerificationRequest;
  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Crypt;
  
  class VerifyEmailController extends Controller
  {   
  
      /**
       * Mark the authenticated user's email address as verified.
       *
       * @param  \Illuminate\Foundation\Auth\EmailVerificationRequest  $request
       * @return \Illuminate\Http\RedirectResponse
       */
      //public function __invoke(EmailVerificationRequest $request)
      public function verify(Request $request)
      {                
          
          try {
              if (Crypt::decrypt($request-&gt;route('hash')) != $request-&gt;user()-&gt;getKey()) {
                  abort(400, 'The link is wrong');
              }
          } catch (DecryptException $e) {
              abort(400, 'The link is wrong');        
          }        
          
          if ($request-&gt;user()-&gt;hasVerifiedEmail()) {                        
              return $request-&gt;wantsJson()
                  ? response([], 204)
                  : redirect()-&gt;intended(RouteServiceProvider::HOME.'?verified=1');
          }        
  
          if ($request-&gt;user()-&gt;markEmailAsVerified()) {
              event(new Verified($request-&gt;user()));
          }
          
          return $request-&gt;wantsJson()
                 ? response([], 204)
                 : redirect()-&gt;intended(RouteServiceProvider::HOME.'?verified=1'); 
      }
  }
  </code></pre>
  <p>The users table already has the <strong>email_verified_at</strong> and <strong>verified</strong> fields, and when I created a user, the <strong>email_verified_at</strong> field is null, then I check the email verification and click the confirmation link, then the user is redirected to the login page and everything is working fine, when I check the database at this point, the email_verified_field is filled with the current date, but the problem is that even if the user doesn't click the verification link or the <strong>email_verified_at</strong> field remainds null, the user can login without problems, I thought that when the user tried to login it would display a message for example: your email is not verified, but this is not happening.
  I am using Laravel 8 with <strong>laravel breeze</strong>, But I am using it only as api, the frontend was made with <strong>Reactjs</strong>.
  What can I do? Thank you.</p>
  <p>Edit: I added this:</p>
  <pre><code>Route::post('/login', [AuthenticatedSessionController::class, 'store'])
                  -&gt;middleware(['guest','verified']);
  </code></pre>
  <p>To avoid unverified users to login, and it doesn't work as expected, it displays a message for unverified users, but also displays the same message for verified users!</p>
  <pre><code>{
      &quot;message&quot;: &quot;Your email address is not verified.&quot;
  }
  </code></pre>
  <p>Maybe sanctum is causing this error, I don't know</p>
  <p>Edit 2:</p>
  <p>Now I added the verified middleware to another protected route:</p>
  <pre><code>Route::get('/posts',[PostsController::class,'index'])-&gt;middleware('verified');
  </code></pre>
  <p>Here works properly, for both users, the problems comes when I use the verified middleware in the login route</p>
  <p>So strange.</p>