Laravel check if user email verified

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Laravel: Checking Email Verification Directly in Your Controller Without Middleware

As a senior developer working with the Laravel ecosystem, we often encounter scenarios where we need fine-grained control over access authorization within specific controller methods, rather than relying solely on global middleware or route definitions. The request—to check if a user is authenticated and has a verified email only for a single action like create—is very common.

While using middleware (like the one you mentioned) is generally the most DRY (Don't Repeat Yourself) way to enforce these rules across an entire application, there are valid reasons why you might need to perform this check directly inside the controller method.

This post will explore how to achieve this specific authorization requirement cleanly within your controller, demonstrating both a direct approach and introducing the more scalable Laravel-native solution using Policies.

The Direct Approach: Checking Model State in the Controller

If you absolutely must perform the check within the controller function itself, the most straightforward way is to access the authenticated user object retrieved via Auth::user() and inspect its attributes. This keeps the logic tightly coupled with the action being performed.

In your specific case, you need to ensure two conditions are met: the user is logged in and their email has been verified.

Here is how you can implement this check directly within your create method:

php
use Illuminate\Support\Facades\Auth;
use App\Models\User; // Assuming your User model is here

public function create()
{
    // 1. Check if the user is authenticated
    if (!Auth::check()) {
        return redirect()->route('login');
    }

    $user = Auth::user();

    // 2. Check if the email is verified
    if (!$user->email_verified_at) {
        // Redirect back or show an error message if verification is missing
        return redirect()->back()->with('error', 'Please verify your email address before proceeding.');
    }

    // If both checks pass, proceed with creating the resource
    // ... rest of your logic (State/City fetching)

    $states = State::orderBy('name', 'asc')->get();
    $state_id  = '1'; // Example static ID
    $cities = City::where('state_id', $state_id)->orderBy('name', 'asc')->get();

    return view('pages.create_product', ['user' => $user, 'states' => $states, 'cities' => $cities]);
}

Analysis of the Direct Approach

This method is explicit and works perfectly for a single function. However, as your application grows, repeating this if statement across dozens of controller methods becomes cumbersome, leading to code duplication and potential inconsistencies if the verification rule ever changes.

The Scalable Solution: Leveraging Laravel Policies

For robust authorization logic, especially when dealing with complex rules like email verification, the recommended Laravel approach is utilizing Policies. Policies allow you to centralize the "what" (authorization rules) away from the "how" (controller execution). This aligns perfectly with how large applications should be structured.

A Policy defines a clear contract for whether a user is allowed to perform an action on a specific model.

Implementing Email Verification via a Policy

  1. Define the Policy: Create a policy for your User model (e.g., UserPolicy).
  2. Define the Rule: Within the policy, define a method that checks the verification status.
  3. Apply in the Controller: Use the built-in Gate or Policy helpers to check permissions before executing the code.

For example, you could define a simple gate:

php
// In your AuthServiceProvider.php (or similar setup)
Gate::define('create-product', function ($user) {
    return Auth::check() && $user->email_verified_at !== null;
});

Then, in your controller, you simply check this gate:

php
public function create()
{
    // Check if the user has permission to perform this action
    if (Auth::user()->can('create-product')) {
        // Proceed with creating the resource and fetching data...
        $user = Auth::user();
        $states = State::orderBy('name', 'asc')->get();
        // ... rest of your logic
        return view('pages.create_product', ['user' => $user, /* ... */]);
    } else {
        return redirect()->route('login')->with('error', 'Access denied. Please ensure your email is verified.');
    }
}

Conclusion

While the direct check inside the controller (as shown in the first example) solves your immediate problem efficiently, it sacrifices scalability. As you continue developing with Laravel, I strongly recommend migrating these types of authorization checks into Policies. This practice adheres to the principles of clean architecture and maintains consistency across your entire application. By leveraging Laravel’s built-in authorization features, you ensure that your application logic remains readable, maintainable, and robust, which is central to building high-quality applications on the platform provided by laravelcompany.com.