I'm using Laravel 9
I want to prevent User to view another User personal information. This is my Policy method
public function viewUser(User $user, User $model)
{
return $user->id === $model->id;
}
and this is Controller method
public function show(User $user)
{
$this->authorize('viewUser', $user);
return view('users.show', compact('user'));
}
It shows 403 as expected
But I want to change status code to 404 like this
public function viewUser(User $user, User $model)
{
return $user->id === $model->id
? Response::allow()
: Response::deny(code: 404);
}
And it's still shows 403 not 404. What am I doing wrong with the Policy? I know I can change response using another approach but my question about Laravel Policies itself.
Route
Route::group([
'middleware' => ['auth'],
'prefix' => 'users/{user}',
'as' => 'users.',
], function () {
Route::get('/', [UserController::class, 'show'])->name('show');
});
CodePudding user response:
In app\Exceptions\Handler.php
in the render()
method you can define what should be done when X
Exception is thrown. That being said, adding below piece of code should do the trick for you:
if ($exception instanceof AuthorizationException) {
$exception = new NotFoundHttpException;
}
return parent::render($request, $exception);
What it does is basically checking if the Exception that is thrown is an AuthorizationException (which policies in Laravel throw) and if that is the case, throw a new NotFoundHttpException (404
). This will however change any and all AuthorizationExceptions to a 404, which is probably not wanted behaviour.
Update:
After digging I found a closed proposal for returning 404.
Personally I feel that a policy should not return anything but a 403 status code, since that is the correct code, something is forbidden. Returning a 404 would not be correct since the policy does not handle X resource not found.
If you'd really want you could change the Handler.php
. I feel like this is not the correct way to use policies however, but that's beside the point.
A user in above mentioned closed proposel used request parameters to check if the route belonged to a certain type, i.e. product and returned a 404 instead of 403. Maybe this can be applied to your use case aswell, check it out here. Hope I've been thorough and it maybe helps.