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

ahoi's avatar
Level 5

Sanctum: CSRF token mismatch. I don't get it.

Hello everybody,

I am having trouble to solve this issue: I don't get SPA auth working because of CSRF.

First of all, I am using httpie to mock requests.

This is how I get the csrf-cookie:

response=$(http -v GET http://api.exampletest/sanctum/csrf-cookie)
xsrf_token=$(echo "$response" | grep -o 'XSRF-TOKEN=[^;]*' | cut -d'=' -f2)

This works:

echo $xsrf_token
eyJpdiI6Ik5xeklxTjBLQVl4bU9wdGNWV0M1dlE9PSIsInZhbHVlIjoieFU5blhZTU5IVEVMMHVEd01zalhuSVdyWmlRTnNzVnVMMUpYMU11RTVhU2ZsL3FacUVuaDE2L1BuYk1GZ0xSaXpTbURkaHdZb1RteTkzRU1CRzluSU1hZWJoZUNOTXFKOTRhUk8wVTkva21xMXV6QlFkSGJUeTlvQ0NjM2pQUSsiLCJtYWMiOiJkNWM5YmI4MDg2NDJiZTk3NTg0ZDUwYzFkZGZiZTZmZDMwZGIzYmE5OGQ0ZDZiODYxNGM5YmNlMzEwZGZiNjg4IiwidGFnIjoiIn0%3D

Now I should eb able to send something to /login, right?

I configured cors.php and sanctum.php:

cors.php:

sanctum.php:

And of course I am setting those values in my .env:

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=true
SESSION_PATH=/
SESSION_DOMAIN=.example.test
SANCTUM_STATEFUL_DOMAINS="web.example.test, .example.test"
0 likes
1 reply
LaryAI's avatar
Level 58

The issue you're encountering with the CSRF token mismatch is a common one when working with Laravel Sanctum and SPAs. Here are a few steps to troubleshoot and resolve the issue:

  1. Ensure Cookies are Sent with Requests: Make sure that your HTTP client (httpie in this case) is sending cookies along with the requests. The CSRF token is stored in a cookie, and it needs to be sent back to the server with the login request.

  2. Correctly Set the X-XSRF-TOKEN Header: Ensure that the X-XSRF-TOKEN header is correctly set with the value of the XSRF-TOKEN cookie.

  3. Check CORS Configuration: Your CORS configuration seems to be permissive enough, but double-check that the supports_credentials option is set to true.

  4. Verify Session Configuration: Ensure that your session configuration is correct and that the session domain matches the domain of your API.

  5. Use the Correct Domain: Make sure that the domain in your .env file matches the domain you are using to make requests.

Here is a step-by-step solution:

Step 1: Fetch CSRF Token and Set Cookies

First, fetch the CSRF token and ensure cookies are stored:

response=$(http -v GET http://api.example.test/sanctum/csrf-cookie)
xsrf_token=$(echo "$response" | grep -o 'XSRF-TOKEN=[^;]*' | cut -d'=' -f2)

Step 2: Send Login Request with Cookies and CSRF Token

Next, send the login request with the X-XSRF-TOKEN header and ensure cookies are included:

http --session=my_session POST 'http://api.example.test/login' \
  'Accept-Language:de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7' \
  'Connection:keep-alive' \
  'DNT:1' \
  'Origin:http://api.example.test' \
  'Referer:http://api.example.test/login' \
  'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36' \
  'X-XSRF-TOKEN:$xsrf_token' \
  email='[email protected]' password='password'

Step 3: Verify CORS and Session Configuration

Ensure your cors.php and sanctum.php configurations are correct. Your cors.php looks fine, but double-check sanctum.php:

// config/sanctum.php
return [
    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),
    'guard' => ['web'],
    'expiration' => null,
    'middleware' => [
        'verify_csrf_token' => \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => \Illuminate\Cookie\Middleware\EncryptCookies::class,
        'add_queued_cookies_to_response' => \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        'start_session' => \Illuminate\Session\Middleware\StartSession::class,
        'share_errors_from_session' => \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    ],
];

Step 4: Check .env Configuration

Ensure your .env file has the correct settings:

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=true
SESSION_PATH=/
SESSION_DOMAIN=.example.test
SANCTUM_STATEFUL_DOMAINS="web.example.test, .example.test"

Step 5: Clear Config Cache

Finally, clear the configuration cache to ensure all changes are applied:

php artisan config:cache
php artisan config:clear
php artisan cache:clear

By following these steps, you should be able to resolve the CSRF token mismatch issue and successfully authenticate your SPA with Laravel Sanctum.

Please or to participate in this conversation.