API requests with axios always unauthorized with Laravel API
I'm not using Passort or any library like that since it's an internal API serving only VueJS to obtain stuff from the database.
If the API is not stateless, meaning that the user is known to be logged in with a standard session cookie, then you can just use the default 'web'
middleware for the API routes.
In the default RouteServiceProvider
, change the mapApiRoutes
function to use the web
middleware instead:
protected function mapApiRoutes()
{
Route::prefix('api')
// ->middleware('api')
->middleware('web')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
That being said, you should really put the API routes behind the default 'auth'
middleware since they're not throttled by default.
In the routes/api.php
file:
Route::group(['middleware' => 'auth'], function() {
Route::get('/latest', 'InternalApiController@latest');
});
And if you want to ensure it's an AJAX request, you can create a simple middleware that checks that the request has the X-Requested-With
header set to XMLHttpRequest
.
class RequestIsAjax
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$request->ajax()) {
return redirect()->route('login.index');
}
return $next($request);
}
}
And register it within the $routeMiddleware
array inside the \App\Http\Kernel
class.
protected $routeMiddleware = [
'ajax' => \App\Http\Middleware\RequestIsAjax::class,
With Laravel 8, I was getting a 401 error when trying to request something from the backend api. Following the accepted answer got me close, but it still didn't work. I believe this was because I have the dashboard on a subdomain as users.mydomain.tld
and where I was using Axios was on the primary domain as mydomain.tld/some/path
. The issue is the path for the session cookies. When re-configuring this, you need to clear all the cookies (dev toolbar). Then re-login like normal after you have made your changes. Else, the cookies will be messed up and you won't see it fixed or you wont be able to login at all until you clear them.
I reverted all the changes I made (following the accepted answer) and pinned down the SESSION_DOMAIN
environment variable being the key ingredient, at least when it comes to the main user's area being on a sub-domain.
In your .env
file:
SESSION_DOMAIN=".yourdomain.tld"
In app/Providers/RouteServiceProvider.php
change api
to web
in the boot()
method:
Route::prefix('api')
//->middleware('api')
->middleware('web')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
In routes/api.php
:
Route::middleware('auth')->get('/user', function (Request $request) {
return $request->user();
});
In your resources/js/bootstrap.js
:
window.axios.defaults.withCredentials = true;
After modifying the bootstrap.js
file, you will need to run npm run dev
again to recompile.
Now, you should be able to use Axios in your frontend JavaScript. Whether it be jQuery or Vue, whatever you are using.
axios.get('/api/user')
.then(response => console.dir(response.data))
.catch(error => console.log(error));