Fixing Unauthenticated Response From Apiuser While Using React And Laravel Sanctum

image
image
image
image
image
image
image
image
Fixing “Unauthenticated” Response from /api/user While Using React and Laravel Sanctum

Fixing “Unauthenticated” Response from /api/user While Using React and Laravel Sanctum

When building a modern single-page application (SPA) with React and Laravel, authentication is a crucial part of the setup. Laravel Sanctum makes it easy to authenticate SPAs via cookies, but many developers encounter the frustrating “Unauthenticated” response from the /api/user route even after login seems successful.

In this article, we will dive deep into why this happens, how Sanctum works, and the step-by-step solutions to resolve this issue with clarity, covering:

  1. What is Laravel Sanctum?
  2. How Sanctum authenticates React SPAs
  3. The common “Unauthenticated” error explained
  4. Step-by-step solution to fix it
  5. Additional tips for production deployments
  6. Final thoughts

1. What is Laravel Sanctum?

Laravel Sanctum provides a featherweight authentication system for SPAs, simple token-based APIs, and mobile applications.

  1. It uses API tokens for mobile apps or external services.
  2. It uses cookie-based authentication for single-page applications built with React, Vue, or Angular, providing CSRF protection and session-based auth seamlessly.

Why choose Sanctum for SPAs?

  1. Uses Laravel’s built-in session and cookie system, reducing JWT complexity.
  2. Automatically handles CSRF tokens for stateful authentication.
  3. Easy to integrate with React or Vue frontends.

2. How Sanctum Authenticates React SPAs

When using Sanctum for SPAs, the flow is:

  1. Frontend loads CSRF cookie by calling /sanctum/csrf-cookie.
  2. Frontend sends login request (/login) with credentials.
  3. Laravel authenticates and attaches session cookies to the browser.
  4. Subsequent API calls (e.g., /api/user) include these cookies, and Sanctum validates them to identify the user.

Important Note

Sanctum requires:

  1. Your frontend to be on the same domain or configured subdomain as your backend or
  2. If cross-domain, correct CORS and cookie settings must be configured for credentials.

3. The “Unauthenticated” Error Explained

When calling /api/user, you may receive:

{
"message": "Unauthenticated."
}

Possible reasons include:

✅ Missing or incorrect CSRF token call

✅ CORS misconfiguration

✅ Cookie not sent with request

✅ Session domain mismatch

✅ Using axios/fetch without { withCredentials: true }

✅ Missing middleware in Laravel routes

4. Step-by-Step Solution to Fix “Unauthenticated” Error

Here is a comprehensive, practical guide to resolve this issue:

Step 1. Backend Setup: Sanctum and CORS Configuration

Install Sanctum

If you haven’t already:

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

Add Sanctum Middleware

In app/Http/Kernel.php, under api middleware group:

'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Ensure this middleware is the first entry in the api group.

Step 2. Configure config/sanctum.php

If using cross-domain setup, update:

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,frontend-domain.com')),

✅ Replace frontend-domain.com with your React app domain.

Step 3. Configure config/cors.php

Ensure CORS settings allow credentials and your frontend origin:

'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000', 'https://your-frontend-domain.com'],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,

supports_credentials must be true for cookies to be sent cross-origin.

Step 4. Frontend Axios/FETCH Setup

If using axios, always include:

axios.defaults.withCredentials = true;

When making requests:


axios.get('http://your-api-domain.com/api/user', { withCredentials: true })

If using fetch, use:

fetch('http://your-api-domain.com/api/user', {
method: 'GET',
credentials: 'include',
});

Without { withCredentials: true }, cookies won’t be sent.

Step 5. Authentication Flow in React

Example authentication flow in React with axios:

import axios from 'axios';

axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'http://your-api-domain.com';

export const login = async (email, password) => {
// Load CSRF cookie first
await axios.get('/sanctum/csrf-cookie');
// Then send login request
await axios.post('/login', { email, password });
// Fetch user details
const { data } = await axios.get('/api/user');
console.log(data);
}

Always call /sanctum/csrf-cookie before /login.

Step 6. Check Session Configuration

In .env, ensure:

SESSION_DRIVER=cookie
SESSION_DOMAIN=.your-domain.com
SANCTUM_STATEFUL_DOMAINS=your-frontend-domain.com

✅ For local setup, SESSION_DOMAIN=localhost works. For production, prefix with a dot for subdomains (e.g. .codehunger.in).

Step 7. Verify Cookies in Browser

Use Developer Tools > Application > Cookies to check:

  1. Is the session cookie set for your API domain?
  2. Does it have HttpOnly, Secure, SameSite settings appropriate for your deployment?

For cross-domain production:

  1. Set SESSION_COOKIE_SAMESITE=None
  2. Set SESSION_SECURE_COOKIE=true (if using HTTPS)

Update .env:

SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=None

5. Additional Tips for Production Deployments

✔️ Use HTTPS

Browsers block cookies with SameSite=None if not served over HTTPS.

✔️ Test with Postman + Browser

Postman does not handle cookies the same way as browsers, so always validate in-browser.

✔️ Clear Cache after Config Changes

php artisan config:clear
php artisan cache:clear

✔️ Avoid mixing API token auth with cookie-based auth unless required.

✔️ Subdomain Consideration

If your API is on api.yourdomain.com and frontend is on yourdomain.com, treat them as same-site with correct SESSION_DOMAIN setup.

6. Final Thoughts

The “Unauthenticated” error from /api/user while using React with Laravel Sanctum is often due to missing CSRF initialization, cookie misconfiguration, or CORS issues. Understanding the flow:

  1. CSRF cookie
  2. Login request
  3. Authenticated API calls

…and ensuring middleware, CORS, and session settings align correctly will resolve this problem.

Key Takeaway

👉 Always remember: CSRF + Correct CORS + Credentials included + Session configuration = Smooth Sanctum Auth.