Search code examples
phplaravelemail-verificationlaravel-8laravel-jetstream

Laravel 8: How do i verify the users email address after registration without having to require login information?


I set up a Laravel 8 installation with Jetstream and implemented a custom user registration, where an event is fired after a successful creation of the database record event(new Registered($user));.

The initial registration process should not require a password yet, because only a selected set of users should be able to login to a dashboard in the future.

After the registration the user gets an email with a verification link, however he still needs to login in order to get verified.

I tried to remove the auth middleware in routes/web.php, however i get an error message after attempting to verify a users email address.

Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
  $request->fulfill();
  return view('home');
})->middleware(['auth','signed'])->name('verification.verify');

Is it possible to verify a users email address without login information?


Solution

  • It is possible.

    You can modify files directly in Jetstream packages however I will present method adding new files and keeping original packages untouched.

    Add new Controller App\Http\Controllers\VerifyEmailController.php

    <?php
    
    namespace App\Http\Controllers;
    
    use App\Models\User;
    use Illuminate\Auth\Access\AuthorizationException;
    use Illuminate\Auth\Events\Verified;
    use Illuminate\Http\Request;
    use Laravel\Fortify\Contracts\VerifyEmailResponse;
    
    class VerifyEmailController extends Controller
    {
        public function __invoke(Request $request)
        {
            $user = User::findOrFail($request->route('id'));
    
            if (! hash_equals(sha1($user->getEmailForVerification()), (string) $request->route('hash'))) {
                throw new AuthorizationException;
            }
    
            if ($user->hasVerifiedEmail()) {
                return app(VerifyEmailResponse::class);
            }
    
            if ($user->markEmailAsVerified()) {
                event(new Verified($user));
            }
    
            return app(VerifyEmailResponse::class);
        }
    }
    

    In web.php add a new route without auth middleware:

    use App\Http\Controllers\VerifyEmailController;
        
    Route::get('/email/verify/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
        ->middleware(['signed', 'throttle:6,1'])
        ->name('verification.verify');