4
votes

I implemented email verification in a Laravel 5.7 project I'm working on. I get the email, but whenever I click on the confirm button or even the url provided in the email, I get a 403 forbidden error.

I have searched for several solutions, but haven't been able to find one to this problem. The only reasonable pointers to this error is this github issue https://github.com/laravel/framework/issues/25716 which has been merged and closed by Taylor Otwell by still this problem persists.

Here's the email I get: enter image description here Here's the error it throws when I click on the button or the actionUrl at the email footer:enter image description here and here's the url shown when the 403 page is displayed https://www.mywebsite.com/email/verify/1?expires=1540140119&signature=fd7dc72b05da6f387b2f52a27bceee533b2256436f211930c1319c7a544067da

Please help me. Thank you

Edits: This problem occurs only in production app. On local, this email verification works but throws 403 on production(live) server. My email service is mailgun, and I can access every other email contents relating to the app except completing email verification. I need help please. Thanks in anticipation

8
When you php artisan route:list, do you get the following middelware for the verification.verify route name: web,auth,signed,throttle:6,1? - emotality
Yes, I get it. I just checked again to confirm - Ehi
Hey @Ehi, did you set your APP_URL in your .env file? - rpm192

8 Answers

11
votes

One of the reasons that was in my case can be that you are already logged in with a normal verified user, and you have clicked on the verification email link. In that case it will shoot 403 . Which is not normal in my opinion, but whatever.

6
votes

For me because manually create verification route. which in laravel 6.x or 7.x The route path for verifying emails has changed. from /email/verify/{id} to /email/verify/{id}/{hash} This probably only happens because I use the rules manually, and not Auth::routes(['verify' => true]) for more information laravel upgrade guide upgrade#email-verification-route-change

3
votes

This typically occurs if your application is running behind some proxies and probably doesn't handle SSL termination itself.

The solution is to add

protected $proxies = '*';

to the TrustProxies middleware.

Reference: https://laracasts.com/discuss/channels/laravel/hitting-403-page-when-clicking-verify-link-in-email-using-new-laravel-verification-57?page=1

1
votes

Turns out, this often happens when you have your laravel app running behind a proxy (apache, nginx etc.) We therefore end up replacing laravel's default 'signed' middleware with our own middleware that checks for https:// links. This StackOverFlow answer here was able to fix this problem for me:

Signed route for email verification does not pass signature validation

0
votes

To use Laravel email verification you must first add the proper routes.

If you take a look at Illuminate/Routing/Router.php you'll see that by default the verify route is disabled.

if($options['verify'] ?? false) 
{
    $this->emailVerification();
}

To enable your verification routes add the following to your web.php

Auth::routes(['verify'=>true]);

Then run

php artisan route:list

to make sure that it's working.

0
votes

Check the verify method inside the VerifiesEmails trait, there they have:

if (! hash_equals((string) $request->route('hash'), sha1($request->user()->getEmailForVerification()))) {
    throw new AuthorizationException;
}

I have dumped this variable $request->route('hash') and it was null, so I overrided it in the VerificationController:

    /**
 * Mark the authenticated user's email address as verified.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function verify(Request $request)
{
    if (! hash_equals((string) $request->route('id'), (string) $request->user()->getKey())) {
        throw new AuthorizationException;
    }

    if (! hash_equals((string) $request->query('hash'), sha1($request->user()->getEmailForVerification()))) {
        throw new AuthorizationException;
    }

    if ($request->user()->hasVerifiedEmail()) {
        return redirect($this->redirectPath());
    }

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

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

And now it works!

0
votes

The problem for me was my APP_URL had a protocol of http and when I clicked on the verification link NGINX automatically redirected the url from http to https that's why the signature validation failed. I updated the APP_URL to have a protocol of https and that resolved my problem.

0
votes

My personal experience with this problem was that I set MAIL_DRIVER to log in the .env file, and Laravel escaped special characters (such as &) when it stored the activation link in the log.

So NEVER use the log for MAIL_DRIVER when you have verification email. (my Laravel version was 5.8).