1

On Laravel 5.6, when I call a route protected by the auth:api middleware I get a 400 response error instead of the 401 I expect.

api.php:

Route::middleware('auth:api')->group(function() {
    //...
}

And the Exception handler:

 public function render($request, Exception $e)
{
    // If the request wants JSON (AJAX doesn't always want JSON)
    if ($request->wantsJson()) {
        // Define the response
        $response = [
            'errors' => 'Sorry, something went wrong.'
        ];

        // If the app is in debug mode
        if (config('app.debug')) {
            // Add the exception class name, message and stack trace to response
            $response['exception'] = get_class($e); // Reflection might be better here
            $response['message'] = $e->getMessage();
            $response['trace'] = $e->getTrace();
        }

        // Default response of 400
        $status = 400;

        // If this exception is an instance of HttpException
        if ($this->isHttpException($e)) {
            // Grab the HTTP status code from the Exception
            $status = $e->getStatusCode();
        }

        // Return a JSON response with the response array and status code
        return response()->json($response, $status);
    }

    // Default to the parent class' implementation of handler
    return parent::render($request, $e);
}

The error:

{
    "errors": "Sorry, something went wrong.",
    "exception": "Illuminate\\Auth\\AuthenticationException",
    "message": "Unauthenticated.",
    "trace": [Here's the trace]
}

Expected behaviour is visible in this answer, though the problem is different.

Why am I getting a 400 with the above instead of a 401 with just the message?

Full code on GitHub.

Michał
  • 868
  • 1
  • 10
  • 36

1 Answers1

0

When the default authentication middleware checks fail, it throws an AuthenticationException. You can change how this exception is handled by creating an unauthenticated function in your Exception\Handler.php file, see below example.

protected function unauthenticated($request, AuthenticationException $exception) {
    if ($request->expectsJson()) {
        return response()->json(['error' => 'Unauthenticated.'], 401);
    }

    return redirect()->guest('login');
}
S. Dev
  • 609
  • 5
  • 18
  • Thanks! I was hoping that I wouldn't have to do that. The error is being caught and sent as JSON, and there is a clause for setting the response code in my code. It's just not working though :P. As a side node, validation errors and other exceptions are also come with 400 and are formatted as above... – Michał Apr 17 '18 at 15:52
  • Where are you setting the response code at the moment? – S. Dev Apr 17 '18 at 16:21
  • `If this exception is an instance of HttpException` note in the first Exception handler, no? – Michał Apr 17 '18 at 16:32
  • `AuthenticationException` isn't an instance of HttpException – S. Dev Apr 17 '18 at 17:01
  • Yeah I was thinking it may not be. Does that mean laravel does not set this up natively? – Michał Apr 17 '18 at 18:36
  • Just tried it at got `Declaration of App\\Exceptions\\Handler::unauthenticated($request, App\\Exceptions\\AuthenticationException $exception) should be compatible with Illuminate\\Foundation\\Exceptions\\Handler::unauthenticated($request, Illuminate\\Auth\\AuthenticationException $exception)` – Michał Apr 17 '18 at 20:10
  • Add `use Illuminate\Auth\AuthenticationException;` with the other `use` lines at the top of the file. – S. Dev Apr 18 '18 at 07:27
  • Yes that should solve it :P! Regardless, I kinda feel this is hack-y. See this answer, thats the behaviour (and notice no setup) that I'm expecting: https://stackoverflow.com/a/46191148/7410951 – Michał Apr 18 '18 at 10:44
  • Looking at the default exception handler, if an AuthenticationException is raised, it first calls `prepareException` which overrides the exception with a HttpException setting the status code to 403. You can use the `unauthenticated` function to output as needed - it's documented functionality and not a hacky workaround. – S. Dev Apr 18 '18 at 16:19
  • I can't figure it out. I've found what you said in the API documentation, but even after adding the function I still get a `400` error with the message Unauthenticated... – Michał Apr 28 '18 at 00:29