php - Laravel 403 THIS ACTION IS UNAUTHORIZED. when email verifying
I looked up in Laravel/8.x
docs and setup routes for email verification. Here are the routes:
Route::get('/email/verify', function () {
return view('auth.verify-email');
})->middleware('auth')->name('verification.notice');
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
$request->fulfill();
return redirect('/home');
})->middleware(['auth', 'signed'])->name('verification.verify');
Route::post('/email/verification-notification', function (Request $request) {
$request->user()->sendEmailVerificationNotification();
return back()->with('message', 'Verification link sent!');
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
When i click on this <a href="{{ route('verification.verify', ['id' => \Illuminate\Support\Facades\Auth::id(), 'hash' => \Illuminate\Support\Facades\Auth::user()->password]) }}" class="text-sm text-gray-700 underline">Verify email</a>
It gives me this error: 403 INVALID SIGNATURE
.
EDIT:
I switched to signedRoute
in my a
tag and now i get 403 THIS ACTION IS UNAUTHORIZED.
.
Here is mechanism that leads to verification.verify
route:
@if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
@auth
<a href="{{ url('/') }}" class="text-sm text-gray-700 underline">Home</a>
<a href="{{ URL::signedRoute('verification.verify', [
'id' =>Auth::id(),
'hash' => Auth::user()->password,
])}}" class="text-sm text-gray-700 underline">Verify email</a>
<a href="{{ route('logout') }}" class="text-sm text-gray-700 underline">Logout</a>
@else
<a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
@endif
@endauth
</div>
@endif
In EmailVerificationRequest
i've changed nothing:
under vendor\Laravel\Framework\src\Illuminate\Founndation\Auth\EmailVerificationRequest
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Http\FormRequest;
class EmailVerificationRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
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;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
/**
* Fulfill the email verification request.
*
* @return void
*/
public function fulfill()
{
if (! $this->user()->hasVerifiedEmail()) {
$this->user()->markEmailAsVerified();
event(new Verified($this->user()));
}
}
/**
* Configure the validator instance.
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*/
public function withValidator($validator)
{
return $validator;
}
}
Answer
Solution:
You need to use URL::signedRoute
to generate signed urls, not the route
helper.
URL::signedRoute('verification.verify', [
'id' => Auth::id(),
'hash' => Auth::user()->password,
]);
You can read here for more information about signed urls: https://laravel.com/docs/8.x/urls#signed-urls
You are receiving a 403 because you are not passing the parameters that the framework is expecting.
URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => Auth::user()->getKey(),
'hash' => sha1(Auth::user()->getEmailForVerification()),
]
);
Source