0

On a project I have I am using Fortify as my BE. I need a multilingual app, therefore I added the 'prefix' => {locale}' to config/fortify.php.

Login, registering, and 2FA, are working ok, but the problem arrives with the email verification process.

If I try to click on the link received by email, it goes to the /email/verify and returns a forbidden page error.

Then if I request to get another verification email it returns the error displayed on the title of the question.

Probably it has something to be with the locale parameter because when I run route::list, the verification.verify route is displayed with the endpoint of {locale}/email/verify/{id}/{hash}, so I assume that the link on the request another mail is causing the error since it is referenced as /email/verify/{id}/{hash}.

So does anyone know how to change it? Or has anyone faced a similar problem regarding Fortify and these localization routes?

1 Answer 1

0

What I had to do was to customize some of the default Fortify functions, extending some classes in order to add the locale parameter to them.

When a new user is registered (event) it sends the verification email (listener), so I had to configure the files involved in this flow.

<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Registered;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class SendEmailVerificationNotification implements ShouldQueue
{
    use Queueable;
    
    public function handle(Registered $event)
    {
        if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
            $event->user->sendCustomVerificationEmailNotification();
        }
    }
}

And create the function sendCustomVerificationEmailNotification on the user's model and the notification CustomVerificationNotification that will be sent.

public function sendCustomVerificationEmailNotification()
    {
        $this->notify(new CustomVerificationNotification);
    }
<?php
namespace App\Notifications;

use Carbon\Carbon;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL;

class CustomVerificationNotification extends VerifyEmail
{
    protected function verificationUrl($notifiable)
    {
        if (static::$createUrlCallback) {
            return call_user_func(static::$createUrlCallback, $notifiable);
        }

        return URL::temporarySignedRoute(
            'verification.verify',
            Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
            [
                'locale' => app()->getLocale(),
                'id' => $notifiable->getKey(),
                'hash' => sha1($notifiable->getEmailForVerification()),
            ]
        );
    }
}

Then in case, the user wants an additional verification email notification, this is handled through a function on the EmailVerificationNotificationController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Http\Controllers\EmailVerificationNotificationController;

class CustomEmailVerificationController extends EmailVerificationNotificationController
{
    /**
     * Send a new email verification notification.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        if ($request->user()->hasVerifiedEmail()) {
            return $request->wantsJson()
                        ? new JsonResponse('', 204)
                        : redirect()->intended(Fortify::redirects('email-verification'));
        }

        $request->user()->sendEmail();

        return $request->wantsJson()
                    ? new JsonResponse('', 202)
                    : back()->with('status', 'verification-link-sent');
    }
} 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.