Implementing email address authentication in an API server using Laravel

Laravel
language

In this article, I will show you how to implement email address authentication in an API server using Laravel.

In this article, we will use the MustVerifyEmail interface, which is newly implemented in Laravel 5.7.
By implementing the MustVerifyEmail interface, the confirmation email will be sent automatically, which is very useful as it eliminates the email sending process.

Implement MustVerifyEmail and HasApiTokens in the User model.

IIn the User model, you need to put MustVerifyEmail as shown in the following code.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasFactory, Notifiable;

    ...
}

When MustVerifyEmail is implemented in the User model interface, an email confirmation notification will be sent automatically.

Email Verification - Laravel - The PHP Framework For Web Artisans

Create an access token after new registration with RegisterController.

We will edit the register method of RegisterController.

IThe following code returns the information after creating a new user (email_verified_at is null).

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Session;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Auth\Events\Registered;

class RegisterController extends Controller
{
    ...

    public function register(Request $request): JsonResponse
    {
        $validate = $this->validator($request->all());

        if ($validate->fails()) {
            return new JsonResponse($validate->errors());
        }

        event(new Registered($user = $this->create($request->all())));

        // Automatic login after creating a new account
        $this->guard()->login($user);

        return new JsonResponse(['user' => $user]);
    }
}

Email address authentication routing

The URL for authentication is shown below.
Clicking on the authentication button provided in the authentication email will open this routing URL, which will be redirected after authentication by VerifyEmailController.

// Verify email
Route::get('/email/verify/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
    ->middleware(['signed', 'throttle:6,1'])
    ->name('verification.verify');

If you need to resend the authentication email, post to the following routing to resend the authentication email.

// Resend link to verify email
Route::post('/email/verify/resend', function (Request $request) {
    $request->user()->sendEmailVerificationNotification();
    return back()->with('message', 'Verification link sent!');
})->middleware(['auth:api', 'throttle:6,1'])->name('verification.send');

If you want to accept API requests only for accounts with authenticated email addresses, you need to protect them with middleware verifications.

Route::middleware(['verified'])->group(function(){
    // Accessible only to users with verified email addresses

});

If you do not want to allow accounts to log in that have not completed email address verification, you need to use $this->getGuard()->user()->hasVerifiedEmail() in LoginController to protect the login.

class LoginController extends Controller
{
    ...

    public function login(Request $request): JsonResponse
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => 'required',
        ]);

        if ($this->getGuard()->attempt($credentials) && $this->getGuard()->user()->hasVerifiedEmail()) {
            $request->session()->regenerate();

            return new JsonResponse(['message' => 'OK!']);
        }

        throw new Exception('Login failed. Please try again.');
    }
}

Verify email addresses with VerifyEmailController

Finally, create a new VerifyEmailController and write it as shown in the following code.

In the VerifyEmailController

  • Email address verification (enter datetime in email_verified_at)
  • Redirect to /email/verify/already-success or /email/verify/success.
<?php
namespace App\Http\Controllers;

use Illuminate\Auth\Events\Verified;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use App\Models\User;

class VerifyEmailController extends Controller
{

    public function __invoke(Request $request): RedirectResponse
    {
        $user = User::find($request->route('id'));

        if ($user->hasVerifiedEmail()) {
            return redirect(env('FRONT_URL') . '/email/verify/already-success');
        }

        if ($user->markEmailAsVerified()) {
            event(new Verified($user));
        }

        return redirect(env('FRONT_URL') . '/email/verify/success');
    }
}

conclusion

In this article, I showed you how to use email address authentication in an API server using Laravel.

The steps to implement email address authentication are as follows

  • Implement MustVerifyEmail and HasApiTokens in User model
  • Create an access token after new registration with RegisterController
  • Email Address Authentication Routing
  • Verify the email address with VerifyEmailController

By implementing the MustVerifyEmail interface, which is newly implemented in Laravel 5.7, you can eliminate the email sending process and easily create an email address verification function.

タイトルとURLをコピーしました