Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Email Verification 5.7 using REST API

How to remake Laravel 5.7 Email Verification for Rest API?

Or is it worth doing everything from scratch?

like image 604
Илья Зеленько Avatar asked Sep 17 '18 07:09

Илья Зеленько


People also ask

How do I send verification email after registering in Laravel?

Model Preparation As you can see by examining your application's App\Providers\EventServiceProvider , Laravel already contains a SendEmailVerificationNotification listener that is attached to the Illuminate\Auth\Events\Registered event. This event listener will send the email verification link to the user.

How do I change the verification email in Laravel?

Laravel provides an option to modify the verification email content. In App\Providers\AuthServiceProvider need to call toMailUsing the method from the boot method. * Register any authentication / authorization services. ->line('Click the button below to verify your email address.


1 Answers

This case works for me. Full project code here.

1) Redesigned VerificationController controller

Removed redirects and made response()->json(...) responses.

<?php

namespace App\Http\Controllers\API\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Verified;

class VerificationController extends Controller
{
    use VerifiesEmails;

    /**
     * Show the email verification notice.
     *
     */
    public function show()
    {
        //
    }

    /**
     * Mark the authenticated user's email address as verified.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function verify(Request $request)
    {
        // ->route('id') gets route user id and getKey() gets current user id() 
        // do not forget that you must send Authorization header to get the user from the request
        if ($request->route('id') == $request->user()->getKey() &&
            $request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        }

        return response()->json('Email verified!');
//        return redirect($this->redirectPath());
    }

    /**
     * Resend the email verification notification.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function resend(Request $request)
    {
        if ($request->user()->hasVerifiedEmail()) {
            return response()->json('User already have verified email!', 422);
//            return redirect($this->redirectPath());
        }

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

        return response()->json('The notification has been resubmitted');
//        return back()->with('resent', true);
    }

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('signed')->only('verify');
        $this->middleware('throttle:6,1')->only('verify', 'resend');
    }
}

2) Added my Notification:

I made it so that the link in the email message led to my frontend and contained a temporarySignedRoute link for the request.

use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailBase;

class VerifyEmail extends VerifyEmailBase
{
//    use Queueable;

    /**
     * Get the verification URL for the given notifiable.
     *
     * @param  mixed  $notifiable
     * @return string
     */
    protected function verificationUrl($notifiable)
    {
        $prefix = config('frontend.url') . config('frontend.email_verify_url');
        $temporarySignedURL = URL::temporarySignedRoute(
            'verification.verify', Carbon::now()->addMinutes(60), ['id' => $notifiable->getKey()]
        );

        // I use urlencode to pass a link to my frontend.
        return $prefix . urlencode($temporarySignedURL);
    }
}

3) Added config frontend.php:

return [
    'url' => env('FRONTEND_URL', 'http://localhost:8080'),
    // path to my frontend page with query param queryURL(temporarySignedRoute URL)
    'email_verify_url' => env('FRONTEND_EMAIL_VERIFY_URL', '/verify-email?queryURL='),
];

4) Added to User model:

use App\Notifications\VerifyEmail;

and

/**
 * Send the email verification notification.
 *
 * @return void
 */
public function sendEmailVerificationNotification()
{
    $this->notify(new VerifyEmail); // my notification
}

5) Added routes

The following routes are used in Laravel:

// Email Verification Routes...
Route::get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
Route::get('email/verify/{id}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::get('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');

They are added to the application if used Auth::routes();.

As far as I understand the email/verify route and its method in the controller are not needed for Rest API.

6) On my frontend page /verify-email(from frontend.php config) i make a request to the address contained in the parameter queryURL

The received URL looks like this:

"http://localhost:8000/api/email/verify/6?expires=1537122891&signature=0e439ae2d511f4a04723a09f23d439ca96e96be54f7af322544fb76e3b39dd32"

My request(with Authorization header):

await this.$get(queryURL) // typical get request

The code perfectly verify the email and I can catch the error if it has already been verified. Also I can successfully resend the message to the email.

Did I make a mistake somewhere? Also I will be grateful if you improve something.

like image 57
Илья Зеленько Avatar answered Sep 17 '22 15:09

Илья Зеленько