Skip to content

CORS & Sanctum (SPA authentication)

ExchangePro uses Laravel Sanctum in stateful (cookie) mode. The Nuxt app and API must be configured so cookies and CSRF tokens work across origins.

How authentication works

mermaid
sequenceDiagram
  participant Browser
  participant Nuxt
  participant API as Laravel API

  Browser->>Nuxt: Open /signin
  Nuxt->>API: GET /sanctum/csrf-cookie
  API-->>Browser: Set XSRF-TOKEN cookie
  Nuxt->>API: POST /api/auth/signin (with X-XSRF-TOKEN)
  API-->>Browser: Set session cookie
  Nuxt->>API: GET /api/user (authenticated)
  1. Frontend fetches CSRF cookie from {API_URL}/sanctum/csrf-cookie.
  2. Login POST includes X-XSRF-TOKEN header.
  3. Laravel session cookie is stored for the API domain.
  4. Subsequent API calls send cookies (credentials: include).

CORS configuration

Origins are configured in backend/.env, not hardcoded in config/cors.php.

By default, FRONTEND_URL is the only allowed origin. For multiple frontends (e.g. www + apex, or local + LAN), set:

ini
FRONTEND_URL=http://localhost:4000

# Optional — full URLs with scheme, comma-separated
CORS_ALLOWED_ORIGINS=http://localhost:4000,http://127.0.0.1:4000,https://yourdomain.com,https://www.yourdomain.com

If CORS_ALLOWED_ORIGINS is omitted, Laravel uses FRONTEND_URL only.

Rules

  • Each entry must be a full origin: scheme + host + port (e.g. https://yourdomain.com).
  • Do not use * when supports_credentials is true.
  • Match the URL users type in the browser (including www if you use it).

After changing .env, clear config cache:

bash
php artisan config:clear

Sanctum stateful domains

File: backend/config/sanctum.php

Prefer setting domains via environment variable instead of editing hardcoded LAN IPs:

ini
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:4000,127.0.0.1,127.0.0.1:4000,yourdomain.com,www.yourdomain.com

Include:

  • Host only (no scheme)
  • Host:port for dev servers

Sanctum treats requests from these domains as “first-party” for session authentication.

Same-site deployment tips

SetupCookie notes
API api.domain.com + app domain.comMay need SESSION_DOMAIN=.domain.com
Same origin /api reverse proxySimplest cookie behavior
Different domains entirelyStrict CORS + correct SANCTUM_STATEFUL_DOMAINS

Admin API middleware

Admin routes use:

text
middleware: auth:sanctum, admin, lastSeen

The admin middleware checks that the logged-in user has role = admin (works with Sanctum cookie sessions).

If admin requests return 401/403, see Troubleshooting.

HTTPS requirement

Production must use HTTPS on both frontend and API so browsers accept Secure cookies.

Quick test

bash
# CSRF cookie (note -c jar for cookies)
curl -c cookies.txt -b cookies.txt \
  https://api.yourdomain.com/sanctum/csrf-cookie

# Login (replace token from XSRF-TOKEN cookie)
curl -c cookies.txt -b cookies.txt \
  -H "X-XSRF-TOKEN: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"secret"}' \
  https://api.yourdomain.com/api/auth/signin

Browser-based login via the UI is the recommended test.

Need help? support@xorinlab.com · Website: xorinlab.com