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

mohamadAbdelhady's avatar

i keep getting csrf token mismatch while trying to log in using laravel sanctum with react spa

react login component

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

 const handleSubmit = async (e) => {
        e.preventDefault();
    
        await axios.get('/sanctum/csrf-cookie')
            .then(() => {
                return axios.post('/api/login', formData);
            })
            .then((response) => {
                console.log('Logged in successfully:', response.data);
                // Maybe redirect or fetch user
            })
            .catch((error) => {
                console.error('Login failed:', error.response?.data || error.message);
                alert("Login failed");
            });
    };

cors.php

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['http://localhost:5173'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

sanctum.php

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,localhost:5173,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort(),
        // Sanctum::currentRequestHost(),
    ))),

login function

        $credentials = $request->validate([
            'email' => 'required|string|email',
            'password' => 'required|string',
        ]);

        if(Auth::attempt($credentials)){
            $request->session()->regenerate();
            return response()->json(['message' => 'Login successful'], 200);
        }

        return response()->json(['message' => 'Invalid credentials'], 401);
    }

env

SESSION_DOMAIN=localhost SANCTUM_STATEFUL_DOMAINS=localhost

1 like
6 replies
vincent15000's avatar

Hmmm ... first why do you have return axios.post('/api/login', formData); instead of axios.post('/api/login', formData); ?

Then have you added this code in you bootstrap/app.php file ?

    ->withMiddleware(function (Middleware $middleware) {
        $middleware->statefulApi();
    })
mohamadAbdelhady's avatar

yes i added this to bootstrap/app.php

the return is put so the promise chain continues correctly.

1 like
mohamadAbdelhady's avatar

also i removed the web middleware from the login route now is not returning mismatch but i am not sure if this is the right way to do it

1 like
GdS's avatar

Hi, I would suggest a more permissive cors.php for development. Also, I think axios is not forwarding csrf cookies.

   // cors.php
    'allowed_origins' => ['*']
   // Set withCredentials to true for all requests
   axios.defaults.withCredentials = true;

When you are ready, remember to restrict cors for production.

Please share some follow-up, hope it helps

1 like
puklipo's avatar

Sanctum's SPA authentication can only be used in the same top-level domain. Subdomains are allowed.
It's different from general SPA.

First, you need to check whether you can achieve what you want with Sanctum.

Most CSRF errors in Sanctum occur because of incorrect usage without understanding this.

1 like

Please or to participate in this conversation.