0

I'm building a frontend in React.js and a backend in Laravel, and I'm trying to implement authentication using Laravel Sanctum.

I've set up the Laravel API, installed Sanctum, and configured the cors, sanctum middleware, and the api.php routes accordingly.

On the React side, I'm trying to make authenticated API requests after logging in, but I'm facing issues where either:

  • The request gets a 401 Unauthorized
  • Or the cookie is not being sent with the request

Things I've tried:

  • Configured withCredentials: true in Axios
  • Set SANCTUM_STATEFUL_DOMAINS in .env to include my React app domain
  • Allowed CORS headers in Laravel's cors.php

Expected:

I want to successfully authenticate and send further requests from React that are recognized by Laravel (via the session or token).

My setup:

  • React (Vite) running on: http://localhost:5173
  • Laravel backend running on: http://127.0.0.1:8000
  • Sanctum config: [Insert any relevant .env or config settings]

Axios login request example:

axios.post('http://127.0.0.1:8000/login', {
  email: '[email protected]',
  password: 'password'
}, {
  withCredentials: true
})

I followed the official Laravel Sanctum documentation to set up authentication between my React frontend and Laravel backend.

Here's what I did:

  • Installed Sanctum via Composer and ran php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
  • Configured middleware: added EnsureFrontendRequestsAreStateful::class in api.php middleware group
  • Set up SANCTUM_STATEFUL_DOMAINS=http://localhost:5173 and SESSION_DOMAIN=.localhost in .env
  • Allowed credentials and origins in config/cors.php
  • Used Axios in React with withCredentials: true
  • Created login and protected route in Laravel using the auth:sanctum middleware

What I expected:

After logging in from the React frontend, I expected:

  • A cookie to be set
  • Laravel to maintain session
  • Authenticated requests to api/user or other protected routes to return user data

But what I got:

  • Login seems successful (no error), but the next request to a protected route returns 401 Unauthorized
  • The cookie doesn't appear to be set in the browser or isn’t being sent with the request

2 Answers 2

1

This is a common issue when integrating Laravel Sanctum with a frontend like React and it's often caused by misalignment between cookie domain configuration, CORS settings, and how the Axios client handles credentials.

Correct way to do this:

In .env of Laravel backend:

SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:5173
APP_URL=http://127.0.0.1:8000

In config/sanctum.php

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost:5173')),

In config/cors.php

return [
    'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['http://localhost:5173'],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,
];

*** supports_credentials: true is required for cookies to be accepted across domains.

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

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

Make sure Axios is configured globally (or per-request) like this:

axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'http://localhost:8000';

** localhost used consistently (no 127.0.0.1)

Login Request:

await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', {
  email: '[email protected]',
  password: 'password',
});

*** You must call /sanctum/csrf-cookie first before logging in to set the XSRF token cookie.

The cookie should be sent automatically because:

  • withCredentials: true
  • CORS allows it
  • Session is active
Sign up to request clarification or add additional context in comments.

Comments

0

Follow these steps to authenticate requests from a React application to a Laravel API using Sanctum. This setup assumes you're running the Laravel backend like http://127.0.0.1:8000 and your React frontend on 127.0.0.1:5173 (Vite).

  1. Laravel Sanctum Setup Install Sanctum

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

Add middleware in app/Http/Kernel.php under api group:

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
  1. ENV Configuration

SANCTUM_STATEFUL_DOMAINS=localhost:5173 SESSION_DOMAIN=localhost

  1. CORS Configuration (config/cors.php)

Make Sure:

'paths' => ['api/*', 'sanctum/csrf-cookie'],
'supports_credentials' => true,
  1. React Frontend (Axios Setup)

    import axios from 'axios';

    axios.defaults.baseURL = 'http://127.0.0.1:8000'; axios.defaults.withCredentials = true;

    // Get CSRF cookie await axios.get('/sanctum/csrf-cookie');

    // Then login await axios.post('/login', { email: '[email protected]', password: 'yourpassword', });

Now you can hit protected routes:

const response = await axios.get('/api/user');
console.log(response.data);
  • Laravel API Route

    Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); });

Common Mistakes to Avoid

  • Forgetting to call /sanctum/csrf-cookie before login

  • Missing withCredentials: true in Axios

  • Wrong SESSION_DOMAIN or SANCTUM_STATEFUL_DOMAINS

  • Not allowing credentials in CORS config

2 Comments

Thank you for the quick answer let me try again with the approach, thank you so much.
Hit a try with the approach and let me know if you find anything else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.