macgroover's avatar

"403 Invalid Signature" every time I try to verify email in Laravel 5.7

Build in Email verification works perfectly on my HTTPS testing server, but it always gives a 403 on my production server which is also HTTPS.

https://mydomain.com/email/verify/1?expires=1543682754&signature=799429150b14376c5a2543b070761decb88926c824cd53ab0c80393772d98dfe

The .env file is correctly set to the https domain, and the email arrives fine with an HTTPS address. I've cleared the config cache, but I'm at a loss at why it would work on one and not the other. I'm not using Heroku etc, so unfortunately another discussion suggesting that doesn't seem to apply here.

Any ideas? Or even where in the source code this might be as it's pretty tricky to track down, and if I could work out how the signature is set it would help.

Thanks!

0 likes
9 replies
ftiersch's avatar
ftiersch
Best Answer
Level 28

For the signature check out the docs here:

https://laravel.com/docs/5.7/urls#signed-urls

Is the email sent from the same host that you're accessing here? If the app key is different the signature wouldn't work because it couldn't decrypt the signature key.

3 likes
macgroover's avatar

Thanks for that info btw. I'm looking in the

/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php

to try to work out why the generated one is not matching when I try to confirm it.

macgroover's avatar

@ftiersch I finally tracked it down thanks to your link. At first I thought it was a bug, but it turned out that an old setting in nginx was adding a query string to all requests. This essentially meant that the original URL was being invisibly changed.

Took forever to track that down, but learn a bit more about Laravel!

Thanks

1 like
agentmarine's avatar

@MACGROOVER - What config option did you change, I am getting a 403 on new signed routes and I've got no errors to explain why...

macgroover's avatar

I can't remember precisely but on my nginx settings I had a setting like this:

location / {
        
        try_files $uri $uri/ /index.php?$query_string&q=foo;
        
    }

Notice the q=... . This was necessary for testing on a previous site I had and somehow got copied over. Since it's not visible in the browser, it was tough to track down.

In other words, if the URL you see in the browser is as expected and you're getting the 403 then it's likely your server is adding something to the URL which Laravel correctly identifies as possible tampering.

Take a look at the docs to see that your nginx settings are as they suggest. Mine aren't exactly the same but it helped my track down that extra query.

apartner_pro's avatar

This help to me)

class VerifyEmailNotification extends Notification { public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable);

    return (new MailMessage)
        ->subject(Lang::get('Verify Email Address'))
        ->line(Lang::get('Please click the button below to verify your email address.'))
        ->action(Lang::get('Verify Email Address'), $verificationUrl)
        ->line(Lang::get('If you did not create an account, no further action is required.'))
        ->line('Thank you for using our application!');
}

protected function verificationUrl($notifiable)
{
    return URL::temporarySignedRoute(
        'verification.verify',
        now()->addMinutes(config('auth.verification.expire', 60)),
        [
            'id' => $notifiable->getKey(),
            'hash' => sha1($notifiable->getEmailForVerification()),
        ]
    );
}

}

ayoolatj's avatar

Double-checking the server logs might be a good shout—sometimes they spill the beans on what's going wrong. Also, peek into the network tab of your browser dev tools when you hit that 403; might give you a clue. Is your production server running any security plugins or firewalls that could be picky about the verification URL? Sometimes those can be a headache. As for the source code, search for where the signature is generated.

dev-mo's avatar

i had same issue in production, my case i am using fortify email verification, behind Cloudflare flexible SSL, the issue was fixed after i add trusted proxies to Laravel project:

->withMiddleware(function (Middleware $middleware) {

    // for signed URLs in production to work behind a cloudflare proxy flexible SSL
    $middleware->trustProxies(
        at: '*',
    );
})
1 like

Please or to participate in this conversation.