The EmailVerificationRequest expects a logged in user available in the request:
public function authorize()
{
if (! hash_equals((string) $this->route('id'),
(string) $this->user()->getKey())) {
return false;
}
if (! hash_equals((string) $this->route('hash'),
sha1($this->user()->getEmailForVerification()))) {
return false;
}
return true;
}
It works well with the web guard as it is expect the user to confirm their email while having their session active.
As there is no user available to the request, the authorize method on EmailVerificationRequest fails and the exception handler redirects you to a route named login (even if there isn't a GET counterpart).
The idea is that a user would confirm their email on a traditional web app, before using a mobile app, or other app that only consumes the API.
You'll need to build your own email verification mechanism to use without a session-based guard, as the built-in one relies on having a logged in user in the request.
From a quick Google search (search term: laravel email verification api) I found these two links:
- https://www.youtube.com/watch?v=Qjs4UqPDbuU
- https://stackoverflow.com/questions/52362927/laravel-email-verification-5-7-using-rest-api
Although they are not using Laravel 8, the solutions presented there would still work on Laravel 8.
A slightly modified version from the solution in the Youtube video would be using a custom FormRequest as this one:
<?php
namespace App\Http\Requests;
use App\Models\User;
use Illuminate\Foundation\Auth\EmailVerificationRequest as BaseEmailVerificationRequest;
class EmailVerificationRequest extends BaseEmailVerificationRequest
{
public function authorize()
{
$user = User::query()->findOrFail($this->route('id'));
if (! hash_equals((string) $this->route('hash'),
sha1($user->getEmailForVerification()))) {
return false;
}
$this->setUserResolver(function () use ($user) {
return $user;
});
return true;
}
}
You'd use this form request instead of the one shipped with the framework. Also, when using this, remove the auth middleware from the route as it would try to authenticate the user before running this Form Request.
Hope this helps.