'Laravel - 403 invalid signature on email verification

I have enabled Email verification on my laravel site.

If they dont do it immediatly, but after a day or two, the link times out.. and they land on a page with 403-invalid signature.

From there they cannot do anything else beside manually editing the link. this is the point where I already lost some registrations. Is there a way to:

a) make this timeout much longer

b) in case of timeout/error land on a page that actually makes sense to the user?



Solution 1:[1]

In laravel 5.8 or above add this lines to config/auth.php

'verification' => [
    'expire' => 525600, // One year in minutes
],

Solution 2:[2]

@Omer YILMAZ answears your "a)" call and I am answearing your "b)" call:

We should disable signed Middleware that validates the URL signature (expiration) and automatically shows 403 page for the verification route, and then we should create a custom logic to validate the URL signature doing whatever we would like if it is invalid (expired).

Laravel 5.7, 5.8, 6.x and 7.x

Changing Auth\VerificationController provided by Laravel:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\VerifiesEmails;

class VerificationController extends Controller
{
    use VerifiesEmails {
        verify as verifyTrait;
    }

    protected $redirectTo = '/';

    public function __construct()
    {
        $this->middleware('auth');
        // $this->middleware('signed')->only('verify'); <-- remove this: it is causing 403 for expired email verification URLs
        $this->middleware('throttle:6,1')->only('verify');
    }

    public function verify(Request $request)
    {
        if (!$request->hasValidSignature()) {
            // some custom message
        }
        else {
            return $this->verifyTrait($request);
        }
    }
}

Laravel 8.x

Changing the example provided by Laravel:

use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\Request;

Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
    if (!$request->hasValidSignature()) {
        // some custom message
    }
    else {
        $request->fulfill();

        return redirect('/home');
    }
})->middleware(['auth', /*'signed' <-- remove this*/])->name('verification.verify');

Solution 3:[3]

The following solution worked for me. Go to the next folder, app/Http/Middleware, and edit the following file TrustProxies.php. Change protected $proxies; edit for the following protected $proxies = ‘*’;

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
    protected $proxies  = '*';

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Omer YILMAZ
Solution 2
Solution 3 Karl Hill