API requests with axios always unauthorized with Laravel API
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# API Requests with Axios Always Unauthorized with Laravel API: Decoding the 401 Error
As developers working with Laravel APIs, integrating frontend tools like Axios can sometimes lead to frustrating authentication errors. A common scenario arises when building internal APIs that don't rely on full-blown systems like Passport or Sanctum, yet we attempt to secure routes using standard middleware.
This post dives deep into the specific issue you are facing: why setting the `auth:api` middleware results in a persistent 401 Unauthorized error when making requests via Axios, even when CSRF token headers seem correctly configured. We will analyze the underlying security principles and provide the correct architectural solution for building secure internal APIs in Laravel.
## The Frustration: Middleware vs. Request Context
You are attempting to use standard session/CSRF-based authentication mechanisms (which Laravel heavily relies on) to secure an API endpoint, even though your application is designed as a simple internal service serving data. When you apply the `auth:api` middleware, Laravel expects to find valid authentication credentials (usually derived from sessions or tokens) attached to the request.
When you use Axios directly, it sends standard HTTP headers. While Laravel’s `bootstrap.js` correctly injects the CSRF token into those headers for cross-origin requests, this mechanism primarily protects against Cross-Site Request Forgery attacks within a traditional session-based web context. It does not automatically satisfy an API route middleware expecting a specific authenticated user state unless that state has been explicitly established or verified by the middleware itself.
The error message `Request failed with status code 401` clearly indicates that, from Laravel’s perspective executing the `auth:api` check, no valid authentication was provided for that endpoint, regardless of the presence of the CSRF token header.
## Why Removing the Middleware Solves the Problem
Your observation—removing the middleware fixes the issue—is the crucial clue. It tells us that for your scenario (an internal API serving data without user logins), you do not need session-based authorization enforced by `auth:api`.
When you remove the middleware:
```php
// Before (Causing 401)
Route::middleware('auth:api')->get('/latest', 'InternalApiController@latestEp');
// After (Working)
Route::get('/latest', 'InternalApiController@latestEp');
```
You are telling Laravel that this route is publicly accessible, requiring no specific user authentication to execute the controller method. This aligns perfectly with building a purely internal service layer where access control is managed at the service level rather than the API gateway level.
## Best Practices for Internal API Security
For internal APIs that serve data only to a known frontend (like your VueJS application), relying solely on session-based middleware can be overly restrictive and introduce unnecessary complexity. A more robust approach often involves implementing custom, lightweight authorization checks tailored specifically to your needs.
### 1. Service-Level Authorization
Instead of using broad authentication middleware for internal endpoints, shift the responsibility of access control into your controller logic. This ensures that security rules are explicitly defined where the data is being requested, which is more transparent and easier to manage in an application built on Laravel principles.
If you need to ensure that only certain parts of your application can hit these routes, you can implement a simple gatekeeper function:
```php
// In InternalApiController.php
public function latestEp()
{
// Example check: Ensure the request originates from a trusted source
// (e.g., checking a specific header or IP if necessary for internal security)
if (! $this->isAuthorizedForInternalAccess()) {
abort(403, 'Forbidden: Access denied.');
}
$data = YourModel::latest()->first();
return response()->json($data);
}
```
### 2. Stateless Token Alternatives (If Needed Later)
While your current setup works by bypassing the middleware, if you ever plan to scale this API or integrate it with future external services, consider stateless token methods like Laravel Sanctum. Sanctum allows you to issue simple token-based authentication for SPAs without needing full session management, providing a clean alternative when dealing purely with client-server communication. As mentioned in official documentation, understanding these mechanisms is key to building scalable applications on the Laravel framework.
## Conclusion
The conflict between the `auth:api` middleware and your Axios requests stems from a mismatch in security expectations. You were applying session-based authentication logic where stateless data access was required. By removing the middleware, you correctly established that this internal API should be accessible without requiring a logged-in user session. For internal services, focus on explicit, service-level authorization rather than relying on general web session checks to resolve your 401 errors. Always design your routes and middleware based on the specific security context of your application, adhering to best practices outlined by the Laravel team.