I have Laravel 5.7 app as API service. I'm trying to get json response while trying to access auth guarded route.
My route:
Route::group(['prefix' => 'auth'], function () {
Route::get('me', 'AuthController@me');
});
method:
public function me()
{
return auth()->user();
}
When I make get request to endpoint described above, I got 500 error:
"message": "Route [login] not defined.",
"exception": "InvalidArgumentException",
Because I use Laravel app as API only service, I don't have any web routes. Let's take a look on handling AuthenticationException:
protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest($exception->redirectTo() ?? route('login'));
}
If we send request with Accept: application/json header, we might get this response: response()->json(['message' => $exception->getMessage()], 401).
I'm using axios on client for making xhr requests, so Accept: application/json header is present. By the way, I don't get json response back.
public function expectsJson()
{
return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
}
Since my request has Accept: application/json header, $this->wantsJson() might be satisfied... What's wrong?
Could you share your application on GitHub?
@TBlindaruk yes, here it is
php artisan jwt:secret is required (I'm using jwt-auth)
@Tarasovych
https://github.com/Tarasovych/issue25636/blob/master/app/Http/Controllers/AuthController.php#L9
You did not have a login action within your controller,
Please change
$this->middleware('auth:api', ['except' => ['login']]);
to
$this->middleware('auth:api');
@TBlindaruk changed. This doesn't affect anything by the way.
Commenting (or removing) this line results correct response:
{
"message": "Unauthenticated."
}
But I can't confirm if this is right solution.
Looks like 2 separate issues to me;
$request->expectsJson() is returning false, so it was hitting your web routeroute('login') exists.You'll need to investigate why $request->expectsJson() is returning false?
@laurencei about 1st issue: can I debug it somehow? Can custom FormRequest be suitable in my case? I guess, I can try isJson() to check whatis the type of request.
Totally agree with 2nd issue as it is an aftereffect of the 1st one.
Commenting (or removing) this line results correct response:
Instead of removing the line, replace it with dd($request); and check the headers.
@AegirLeet thank you!
So far:
dd($request):#json: null
...
#acceptableContentTypes: null
...
#headers: array:3 [â–¼
"host" => array:1 [â–¶]
"user-agent" => array:1 [â–¶]
"accept" => array:1 [â–¼
0 => "application/json"
]
]
dd($request->ajax()) returns falsedd($request->isJson()) returns falseSeems a bit strange for me... I thought this
"accept" => array:1 [â–¼
0 => "application/json"
]
is enough to satisfy json request.
OK, I've looked into this and I'm pretty sure it has nothing to do with JSON or the handling of the AuthenticationException, because the AuthenticationException is never even thrown. Try dumping $request->expectsJson() - does this return true? It probably does.
This line is indeed the problem. It's called when the parent tries to construct the Exception:
throw new AuthenticationException(
'Unauthenticated.', $guards, $this->redirectTo($request)
);
But the login route doesn't exist by default, so the route('login') throws an InvalidArgumentException.
This bug is present even in a fresh Laravel install:
laravel new auth-test
cd auth-test
php artisan serve
and then
curl -H "Accept: application/json" http://localhost:8000/api/user
and you will see the same Exception.
This bug seems to have been introduced in https://github.com/laravel/laravel/commit/a14e62325cbe82a615ccd2e80925c75cb0bf1eaf.
Workaround: Add a route named "login" or remove the call to route('login') from the Middleware.
@AegirLeet
dd($request->expectsJson()) returns true
Going to remove route('login') call for now.
I'll be closing this, as Taylor has said in the PR that you are free to change this in your own application.
Let me know if there is another reason to keep this ticket open. Thanks.
You should use Accept header set to application/json in your request.
Most helpful comment
OK, I've looked into this and I'm pretty sure it has nothing to do with JSON or the handling of the
AuthenticationException, because theAuthenticationExceptionis never even thrown. Try dumping$request->expectsJson()- does this returntrue? It probably does.This line is indeed the problem. It's called when the parent tries to construct the Exception:
But the login route doesn't exist by default, so the
route('login')throws anInvalidArgumentException.This bug is present even in a fresh Laravel install:
and then
and you will see the same Exception.
This bug seems to have been introduced in https://github.com/laravel/laravel/commit/a14e62325cbe82a615ccd2e80925c75cb0bf1eaf.
Workaround: Add a route named "login" or remove the call to
route('login')from the Middleware.