The Authorize Attribute

Laravel 13 2,157 's #[Authorize] (Illuminate\Routing\Attributes\Controllers) attaches the can middleware from the controller. It takes the ability, then a route parameter, a class, or both in an array ([Comment::class, 'post']); on the class it covers every action, narrowed by only: or except:. Here OrderPolicy::view hides other people's orders behind a 404:

OrderController::show and OrderPolicy::viewPHP
#[Authorize('view', 'order')]
public function show(Order $order): array { return $order->only('id', 'user_id', 'status'); }
public function view(User $user, Order $order): Response     // in OrderPolicy
{
    return $user->id === $order->user_id || $user->hasRole('staff')
        ? Response::allow() : Response::denyAsNotFound();
}

$ curl 3,008  -si -b ben.jar -H "$J" $B/orders/1; echo

HTTP/1.1 404 Not Found

...

{

    "message": "Not Found"

}

$ try -b ben.jar $B/orders/99

404 {"message":"No query results for model [App\\Models\\Order] 99"}

Ben asks for Ann's order 1, then for order 99, which does not exist

route:list -v lists Authorize:view,order on the route. Ben's HTML 404 page matched the one for order 99 byte for byte, but the JSON messages differ, so an API still leaks existence; with denyAsNotFound('Order not found.') and ->missing(fn () => abort(404, 'Order not found.')) on the route, both answered alike. Closure gates work too: refund() carries #[Authorize('refund-order', 'order')].