Search code examples
laravellaravel-5.7laravel-authorization

Laravel 5.7: User Not Set When Throwing NotFoundHttpException


I am overriding the rendering of a couple of exceptions in the App\Exceptions\Handler so I can return custom error pages. However, on some of the exceptions the auth()->user() is not set.

In the render-method, I am just dumping the user like this:

public function render($request, Exception $exception)
{
    dd(auth()->user());

    return parent::render($request, $exception);
}

When the exceptions are of the type NotFoundHttpException, the user isn't set. What would be the best solution for getting the user in these exceptions?


Solution

  • Here's the solution, but read on for a different recommendation.

    By default, Laravel's authentication runs via the session. The session is explicitly started in the web middleware group.

    If a route is not wrapped in the web middleware group (as a non-existent / 404 route would be), the middleware doesn't run, and the session isn't started. Therefore Laravel can't know if there is a session user.

    Best solution: define a fallback route which was built for exactly this purpose.

    Another solution, with gotchas: move the StartSession middleware into the global group that runs on every request.

    /app/Http/Kernel.php:

    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
        // +++ MOVED SESSION START HERE BELOW +++
        \Illuminate\Session\Middleware\StartSession::class,
    ];
    

    But, should you...?

    First, there's a reason the session doesn't load on every request by default: it creates extra overhead that might not be needed on every request. For example, if your website is configured to always use Laravel as the request handler, every 404 will route through Laravel. And there are a lot - crawlers and bots are constantly scouring the web for known insecure web paths. Take a look at your access logs.

    Also, if you create self-contained error pages that don't depend on external application logic, you can reuse them at the server level. If Apache or Nginx throws an error, Laravel won't be there at all to dictate the output.

    TL;DR: You can enable sessions on 404 and other pages, but understand the trade-offs. Personally, I recommend avoiding application logic on error pages.