Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Verify Email Without Asking the User to Login to Laravel

Tags:

I am developing a Laravel application. My application is using Laravel built-in auth feature. In the Laravel auth when a user registers, a verification email is sent. When a user verifies the email click on the link inside the email, the user has to login again to confirm the email if the user is not already logged in.

VerificationController

class VerificationController extends Controller {     use VerifiesEmails, RedirectsUsersBasedOnRoles;      /**      * Create a new controller instance.      * @return void      */     public function __construct()     {         $this->middleware('auth');         $this->middleware('signed')->only('verify');         $this->middleware('throttle:6,1')->only('verify', 'resend');     }      public function redirectPath()     {         return $this->getRedirectTo(Auth::guard()->user());     } } 

I tried commenting on this line.

$this->middleware('auth'); 

But it's s not working and instead, throwing an error. How can I enable Laravel to be able to verify email even if the user is not logged in?

like image 850
Wai Yan Hein Avatar asked Dec 21 '18 13:12

Wai Yan Hein


2 Answers

First, remove the line $this->middleware('auth');, like you did.

Next, copy the verify method from the VerifiesEmails trait to your VerificationController and change it up a bit. The method should look like this:

public function verify(Request $request) {     $user = User::find($request->route('id'));      if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {         throw new AuthorizationException;     }      if ($user->markEmailAsVerified())         event(new Verified($user));      return redirect($this->redirectPath())->with('verified', true); } 

This overrides the method in the VerifiesUsers trait and removes the authorization check.

Security (correct me if I'm wrong!)

It's still secure, as the request is signed and verified. Someone could verify another user's email address if they somehow gain access to the verification email, but in 99% of cases this is hardly a risk at all.

like image 86
Wouter Florijn Avatar answered Oct 09 '22 19:10

Wouter Florijn


Here's a more future proof solution to the problem:

class VerificationController extends Controller {      // …      use VerifiesEmails {         verify as originalVerify;     }      /**      * Create a new controller instance.      *      * @return void      */     public function __construct()     {         $this->middleware('auth'); // DON'T REMOVE THIS         $this->middleware('signed')->only('verify');         $this->middleware('throttle:6,1')->only('verify', 'resend');     }      /**      * Mark the authenticated user's email address as verified.      *      * @param Request $request      * @return Response      *      * @throws AuthorizationException      */     public function verify(Request $request)     {         $request->setUserResolver(function () use ($request) {             return User::findOrFail($request->route('id'));         });         return $this->originalVerify($request);     } } 

So when an email confirmation link is clicked by an unauthenticated user the following will happen:

  1. User will be redirected to the login view 1
  2. User enters credentials; logs in successfully 2
  3. User will be redirect back to the email confirmation URL
  4. Email will be marked as confirmed

1 The email will not be marked as confirmed at this point.

2 The user may enter bad credentials multiple times. As soon as he enters the correct credentials he will be redirected to the intended email confirmation URL.

like image 32
Martin Avatar answered Oct 09 '22 20:10

Martin