How to implement Laravel’s Must Verify Email feature in the API registration

Laravel provides us with an amazing feature called Must Verify Email which makes email verification a breeze by just writing 2–3 lines of code really. But unfortunately there is no provision for applying the same feature in API, especially if you are using same auth user table to register in API . This threw me off for a while and there wasn’t many resource online , when i finally got around it , turned out to be very simple. So here i am going to share with you how to apply the same feature in your API registration as one stop solution. We will basically recreate the must verify email feature for API. Follow along ….

Let’s install a fresh installation of Laravel, in my case I named my project as “email”, runn the following command to install laravel

composer create-project --prefer-dist laravel/laravel email

Laravel comes ship with users table migration which looks like this

class CreateUsersTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }
}

As you can see that laravel includes ‘email_verified_at’ in it’s schema which when we use Must Verify Email changes from null to the current timestamp , you can check the docs for more info.

Before we implement the email verification feature we need to run the artisan command to make the authorisation scaffoldings type in the following command to enable auth:

php artisan make:auth

Once the auth is generated you can simply include the following in your User Model as mentionad in the docs

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;
    // ...
}

And you can simply include the following in your web route

Auth::routes(['verify' => true]);

Add the middleware in the route to protect it like so

Route::get('profile', function () {
// Only verified users may enter...
})->middleware('verified');

So far we have only talked about how we can implement the email verification in the web route now coming to the topic i will guide you how we can replicate the same for API

Let’s start with recreating the VerificationController that you can find under app/http/controllers/auth/VerificationController only for an API let’s name it “VerificationApiController” run the following command to make the controller

php artisan make:controller VerificationApiController

And just add the follwoing code inside the controller

<?php

namespace App\Http\Controllers;

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

class VerificationApiController 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)
    {
        $userID = $request[‘id’];
        $user = User::findOrFail($userID);
        $date = date(“Y-m-d g:i:s”);
        $user->email_verified_at = $date; // to enable the “email_verified_at field of that user be a current time stamp by mimicing the must verify email feature
        $user->save();
        return response()->json(‘Email verified!’);
    }

    /**
    * 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);
    }
}

Now let’s create our own notification which will mimic the Must Verify Email notification , just create a folder under the app folder called “Notifications” and create a file named “VerifyApiEmail.php” and paste in the following code:

<?php

namespace App\Notifications;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailBase;

class VerifyApiEmail extends VerifyEmailBase
{
    /**
    * Get the verification URL for the given notifiable.
    *
    * @param mixed $notifiable
    * @return string
    */
    protected function verificationUrl($notifiable)
    {
        return URL::temporarySignedRoute(
        ‘verificationapi.verify’, Carbon::now()->addMinutes(60), [‘id’ => $notifiable->getKey()]
        ); // this will basically mimic the email endpoint with get request
    }
}

Now all you have to do for it to work is bring in the notification that you created into your User Model like so use App\Notifications\VerifyApiEmail;
and add the following method inside your user Model

public function sendApiEmailVerificationNotification()
{
    $this->notify(new VerifyApiEmail); // my notification
}

You are almost done now all you have to do is specify the route “‘verificationapi.verify” in your api route , it’s important to note that you need to add the following routes inside your api route for it to work

Route::get(‘email/verify/{id}’, ‘VerificationApiController@verify’)->name(‘verificationapi.verify’);
Route::get(‘email/resend’, ‘VerificationApiController@resend’)->name(‘verificationapi.resend’);

The above code will take care of email verification and getting the proper response as “Email Verified”. But we still need to be able to send the email notification to the email of the user trying to register via api , for that let’s make a controller to handle the api registration request by the user. Let’s call it UsersApiController , run the following command to make the controller

php artisan make:controller UsersApiController

and paste in the following code in it

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Hash;
use Auth;
use Validator;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Auth\Events\Verified;

class UsersApiController extends Controller
{
    use VerifiesEmails;

    public $successStatus = 200;

    /**
    * login api
    *
    * @return \Illuminate\Http\Response
    */
    public function login()
    {
        if (Auth::attempt([‘email’ => request(‘email’), ‘password’ => request(‘password’)])) {
            $user = Auth::user();
                if ($user->email_verified_at !== NULL) {
                    $success[‘message’] = “Login successfull”;
                    return response()->json([‘success’ => $success], $this-> successStatus);
                } else {
                    return response()->json([‘error’=>’Please Verify Email’], 401);
                }
            } else {
            return response()->json([‘error’=>’Unauthorised’], 401);
        }
    }

    /**
    * Register api
    *
    * @return \Illuminate\Http\Response
    */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            ‘name’ => ‘required’,
            ‘email’ => ‘required|email’,
            ‘password’ => ‘required’,
            ‘c_password’ => ‘required|same:password’,
        ]);

        if ($validator->fails()) {
            return response()->json([‘error’=>$validator->errors()], 401);
        }

        $input = $request->all();
        $input[‘password’] = Hash::make($input[‘password’]);
        $user = User::create($input);
        $user->sendApiEmailVerificationNotification();
        $success[‘message’] = ‘Please confirm yourself by clicking on verify user button sent to you on your email’;
        return response()->json([‘success’=>$success], $this-> successStatus);
    }

    /**
    * details api
    *
    * @return \Illuminate\Http\Response
    */
    public function details()
    {
        $user = Auth::user();
        return response()->json([‘success’ => $user], $this-> successStatus);
    }
}

Now all we need to do is add the routes to tie up with the methods in our controller as following , again make sure to add this in your api routes

Route::post(‘login’, ‘UsersApiController@login’);

Route::post(‘register’, ‘UsersApiController@register’);

Route::group([‘middleware’ => ‘auth:api’], function() {
    Route::post(‘details’, ‘UsersApiController@details’)->middleware(‘verified’);
}); // will work only when user has verified the email

Congratulations now you can recieve the email via Api registration , you can test the result in Postman by simply sending a POST Request to
yourUrl/api/register — to register and you should get an email and you can simply click on the link at the email that you have recieved you will get a response as “Email verified” and user is now verified.

Hope this article helps you in solving your API email verification in laravel . Please feel free to reach me out for any queries or doubt.

Tags: No tags

Comments are closed.