Laravel sanctum check if user is authenticated
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# How to Check if the User is Authenticated When Using Laravel Sanctum
As developers building modern APIs with Laravel, understanding how authentication flowsâespecially with token-based systems like Sanctumâis crucial. You've encountered a common point of confusion: why does checking `$request->user()` sometimes return `null` even when a token is present in the header? The answer lies in understanding the separation between route-level authorization (middleware) and request-level context (the user object).
This post will dive deep into how Laravel Sanctum authenticates requests and demonstrate the correct, robust way to check for authentication status within your controllers, regardless of whether you use middleware on the route.
## Understanding the Sanctum Authentication Flow
Laravel Sanctum relies heavily on middleware to establish the authenticated state for a request. When you add `middleware('auth:sanctum')` to a route, Laravel executes the Sanctum guard, validates the provided token, and successfully injects the corresponding `User` model into the request object. This successful execution is what populates `$request->user()`.
If you access a route *without* this middleware, the request bypasses the entire authentication process, meaning no user context is established by Sanctum for that specific request cycle. Therefore, if you attempt to call `$request->user()` on an unprotected route, it will correctly return `null` (or whatever value Laravel defaults to), confirming that no authenticated user has been associated with that request session.
## The Correct Way to Check Authentication in Controllers
The method you proposedâchecking `$request->user()` inside your controllerâis fundamentally the correct way to query the currently authenticated user *if* authentication has successfully occurred upstream.
However, if your goal is to handle both authenticated and unauthenticated scenarios gracefully within a single controller method, you need to treat the result of `$request->user()` as the source of truth for authorization decisions.
### Example Demonstration
Let's refine the example to show the distinction clearly:
**Scenario 1: Unprotected Route (No Middleware)**
If we hit this route without Sanctum middleware, the request context is empty regarding authentication.
```php
// api.php
Route::get('testauth_unprotected', [MyTestController::class, 'testAuthUnprotected']);
```
**Controller Implementation:**
```php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MyTestController extends Controller
{
public function testAuthUnprotected(Request $request)
{
// In this case, the request context is not authenticated by Sanctum.
if ($request->user()) {
return "Authenticated (Error State)";
} else {
return "Guest (Correctly Unauthenticated)"; // This will be returned
}
}
}
```
**Scenario 2: Protected Route (With Middleware)**
When the `auth:sanctum` middleware is applied, Sanctum successfully authenticates the request and populates `$request->user()`.
```php
// api.php
Route::get('testauth_protected', [MyTestController::class, 'testAuthProtected'])->middleware('auth:sanctum');
```
**Controller Implementation:**
```php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MyTestController extends Controller
{
public function testAuthProtected(Request $request)
{
// Because the middleware ran successfully, $request->user() is populated.
if ($request->user()) {
return "Authenticated (Success)"; // This will be returned
} else {
// This branch should theoretically not be reached if middleware worked correctly.
return "Guest (Unexpected State)";
}
}
}
```
## Best Practices: Relying on Middleware for Security Boundaries
While checking `$request->user()` is useful for fine-grained logic, it is crucial to remember that **middleware should always be your primary gatekeeper for security boundaries.**
Relying solely on an internal check can lead to subtle security gaps if a developer forgets to apply the necessary middleware. In larger applications, especially when dealing with complex authorization rules, you should let Laravel's built-in pipeline manage authentication first. This aligns perfectly with the principles of building secure APIs, much like adhering to the architectural guidelines found on the [Laravel Company website](https://laravelcompany.com).
If a route requires authentication, applying `middleware('auth:sanctum')` ensures that *only* authenticated requests ever reach your controller logic. If the user is not authenticated, they are blocked before your code even executes.
## Conclusion
To summarize, there is no magic bypass to completely ignore Sanctum's security checks; middleware remains the definitive way to establish authentication context for a request. The check `$request->user()` is simply the mechanism Laravel provides you to access that established context *after* the necessary authentication has been successfully performed by upstream middleware. Use middleware for authorization boundaries and use `$request->user()` for application-level logic based on that established status.