Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SalmaNegm's avatar

Laravel Sanctum SPA Authentication Fails Between Localhost Frontend and Remote Backend

I'm developing a web application using Laravel (backend) and Next.js (frontend) with Laravel Sanctum SPA cookie based session authentication. I've deployed the Laravel backend on abc.xyz.org, while developing the frontend on localhost:3000.

Current Setup:

  • Backend: Laravel 10 (deployed on abc.xyz.org)
  • Frontend: Next.js 14.2 (running on localhost:3000)
  • Authentication: Laravel Sanctum SPA cookie-based session authentication
  • Authentication Mechanism: LDAP for Active Directory, but using a user that does not exist in the directory.

Issue:

  • Production Environment: Works perfectly when both frontend and backend are on the same top-level domain.
  • Local Development:
    • Login works after making adjustments (see What I Tried).
    • Subsequent requests fail with a 403 Forbidden error because auth()->user() is null.

What I Have Already Tried:

  1. CORS Configuration:

    • Added frontend's full URL to allowed_origins in config/cors.php.
  2. CSRF Middleware:

    • Added api/* to $except in app/Http/Middleware/VerifyCsrfToken.php.

    Result: These changes allowed login to succeed, but subsequent requests still fail with 403 Forbidden.

Observations:

  • Laravel Documentation: For cookie-based authentication, the SPA and API must share the same top-level domain.
  • Current Setup:
    • Backend: abc.xyz.org
    • Frontend: localhost:3000 (does not share the same domain).

Environment Details:

Laravel Version: 10

Laravel Sanctum Version: 3.3

Next.js Version: 14.2

APP_NAME='ABC'
APP_ENV=production
APP_KEY=base64:rwerkjl34lkjh345jkhkj56hkjh345kj=
APP_DEBUG=true
APP_URL=backend_url

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=abc
DB_USERNAME=abc
DB_PASSWORD=abc123

BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=cookie
SESSION_LIFETIME=120

Desired Outcome:

  • Establish a reliable authentication mechanism that works consistently across both local development and production environments.
  • Eliminate the need for frontend developers to set up the backend locally for development.
0 likes
1 reply
maxxd's avatar

Have you tried updating your .hosts file to point localhost:3000 to (for instance) api.xyz.org and updating the API endpoint in your code? Not tried, so no guarantees, but maybe?

Please or to participate in this conversation.