Laravel Email Verification for Vue SPA Laravel Email Verification for Vue SPA vue.js vue.js

Laravel Email Verification for Vue SPA


Faced the same issue with my angular SPA. Not sure you still need help but hope my answer will help somebody.

So while laravel UrlGenerator::signedRoute isn't flexible enough (You can subscribe to this idea. Not the same case, but related to this) we have to implement url signature on our own.

In your VerifyEmail class:

    protected function verificationUrl($notifiable)    {        // collect and sort url params        $params = [            'expires' => Carbon::now()                ->addMinutes(Config::get('auth.verification.expire', 60))                ->getTimestamp(),            'id' => $notifiable->getKey(),            'hash' => sha1($notifiable->getEmailForVerification()),        ];        ksort($params);        // then create API url for verification. my API have `/api` prefix,        // so i don't want to show that url to users         $url = URL::route(            'api:auth:verify',            $params,            true        );        // get APP_KEY from config and create signature        $key = config('app.key');        $signature = hash_hmac('sha256', $url, $key);        // generate url for yous SPA page to send it to user        return url('verify-email') . '?' . http_build_query($params + compact('signature'), false);    }

After that in your SPA you should get url params and invoke API request. I'll specify Angular example but it should be easy to adapt it to Vue.

// on component loadngOnInit() {  // get query params from current route     this.route.queryParamMap.subscribe(params => {    // generate API url. Make sure your query params come in the same order    // as in signature generation. By default signature check middleware     // extracts `signature` param so `expires` is the only param that    // is checked so order doesn't matter, but if you need another params -    // it can turn into a problem     const url = this.router.createUrlTree(['api', 'auth', 'verify', data.id, data.hash],      {queryParams: {expires: data.expires, signature: data.signature}}).toString();    // make API request. if signature check fails - you will receive 403 error    return this.http.get(url).subscribe();  });}

Another easier way i see is to generate direct API url and send it to user as you did. And after verifying just redirect browser to your SPA. I just can't understand why it don't work in your case. Maybe you have some rewrite rules in your webserver config so your actual domain name doesn't match with your APP_URL? Or maybe you serve your API in another port?


The solution for this is pretty straightforward.Using the temporarySignedRoute you need to specify the route, the default is verification.verify, expiration time and parameters.

<?phpnamespace App\Notifications;use Illuminate\Notifications\Notification;use Illuminate\Support\Facades\URL;use Carbon\Carbon;use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailBase;class VerifyEmail extends VerifyEmailBase{    /**     * Get the verification URL for the given notifiable.     *     * @param  mixed  $notifiable     * @return string     */    protected function verificationUrl($notifiable)    {      return URL::temporarySignedRoute(          'verification.verify',           now()->addMinutes(60),           ['id' => $notifiable->id, 'hash' => sha1($notifiable->getEmailForVerification())]    );    }}