Laravel email verification - Forced to be logged in
Asked Answered
T

1

6

After following the installation for enabling the new built-in email verification, all is working good (sending email after registration and clicking the activation enable the account).
But, I'm faced with the case where the user must be logged-in in order for the verification process to engage. Meaning, if the user is not logged in prior to use the verification link, he will be redirected to the login page and then be presented the /resources/view/auth/verify.blade.php page.

I am reaching out to the community to see if this it intentional, a bug or something I'm doing wrong? Did someone run in the same situation?

The site I'm setting up have public access to most pages, but restricted to some (for now the user portal). I set up the routes/web.php as follow:

// Authentication
Auth::routes(['verify' => true]);
Route::group(['middleware' => ['auth', 'verified'], 'as' => 'portal.', 'prefix' => '/portal'], function () {
    Route::get('/', 'PortalController@index');
    Route::get('/profile', 'PortalController@index')->name('profile');
    Route::get('/orders', 'PortalController@index')->name('orders');
});

By tracing the verification process, I was able to find out the process is forcing a log-in in the VerificationController constructor via the middleware shown below.

public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('signed')->only('verify');
        $this->middleware('throttle:6,1')->only('verify', 'resend');
    }

By commenting the first line or adding ->except('verify'), the log-in page is not shown but an error is thrown at the Traits VerifiesEmails method Verify like below, since the user is obviously not logged it (the $request->user() is null).

public function verify(Request $request)
    {
        if ($request->route('id') == $request->user()->getKey() &&
            $request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        }

        return redirect($this->redirectPath())->with('verified', true);
    }

My question, is there a way to get it to work without being loged-in beforehand, or is this the way the Verification process is implemented in 5.7? ... or what am I doing wrong?

Tardif answered 23/10, 2018 at 12:41 Comment(0)
J
7

is there a way to get it to work without being loged-in beforehand, or is this the way the Verification process is implemented in 5.7? ... or what am I doing wrong?

This is the way the Verification process is implemented in Laravel 5.7. Laravel uses signed URLs for verification. The URL is generated with an id parameter (id as user ID) and when the user clicks on the verification link, 3 checks are done:

  1. Is the signature valid? (signed middleware)
  2. What's the user ID in the signature? That's the ID that would ultimately be validated
  3. Does the currently logged in user have the same ID?

You can always remove the third check by overriding the verify method in your VerificationController like so:

public function verify(Request $request)
{

    $userId = $request->route('id');
    $user = App\User::findOrFail($userId);

    if ($user->markEmailAsVerified()) {
        event(new Verified($user));
    }

    return redirect($this->redirectPath())->with('verified', true);
}
Jorgensen answered 23/10, 2018 at 16:52 Comment(1)
I appreciate your detailed explanation Paras. Makes sens the way you explain it. ThxTardif

© 2022 - 2024 — McMap. All rights reserved.