Axios not sending XSRF token with headers

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Axios and Laravel Sanctum: Solving the XSRF Token Mismatch Mystery Integrating a modern Single Page Application (SPA), like one built with Vue/Quasar, with a backend API secured by Laravel Sanctum introduces specific complexities around cross-origin communication and CSRF protection. When developers encounter issues where the token works perfectly in tools like Postman but fails within an HTTP client library like Axios, it usually points to subtle differences in how cookies, credentials, and headers are managed between the two environments. This post dives deep into why your Axios setup might be failing to send the necessary `X-XSRF-TOKEN` header when interacting with a Laravel Sanctum API, and provides the robust solution. ## Understanding the Laravel Sanctum CSRF Flow Laravel Sanctum uses stateful authentication, often relying on session cookies for security. The process you described involves two critical steps: 1. **Token Acquisition:** Making a request to `/sanctum/csrf-cookie` which instructs the server to set a CSRF token cookie in the browser. 2. **Token Usage:** Subsequent requests (like POSTs) must include this token, typically as an `X-XSRF-TOKEN` header, for Sanctum to validate the request against the cookie state. When you successfully use Postman, it often handles the session and cookie management in a way that bypasses or explicitly manages the necessary cross-origin setup that Axios sometimes struggles with when dealing with complex credential flows. ## The Axios and Cookie Dilemma Your configuration correctly sets `api.defaults.withCredentials = true;`, which is essential for telling Axios to send cookies along with requests. However, this setting alone doesn't guarantee that the cookie received from `/sanctum/csrf-cookie` is automatically read and injected into subsequent request headers in the specific way Sanctum expects across different origins. The issue often isn't that the token isn't *available*, but that Axios isn't correctly reading the cookie set by the initial endpoint and attaching it to the outgoing request header, especially when running from a different origin (localhost:8080) than the API server. ## The Solution: Explicitly Handling Tokens in Axios Since you are managing the token acquisition flow manually, the most reliable solution is to ensure that the acquired CSRF token is explicitly retrieved and attached to every subsequent request made by Axios. This bypasses potential ambiguities in automatic cookie handling across origins. Here is how you can refactor your logic to ensure the token flows correctly: ### Step 1: Fetch the Token and Store It When you call `/sanctum/csrf-cookie`, you must read the response body to extract the token that Sanctum sets, or rely on the cookie being present. Since the goal is to explicitly send it via a header, we will focus on ensuring the necessary information is available. ### Step 2: Attaching the Token Manually Instead of relying solely on cookies, ensure your Axios instance includes the acquired token in the headers for authenticated routes. ```javascript import Vue from 'vue'; import axios from 'axios'; Vue.prototype.$axios = axios; const apiBaseUrl = "https://someweburl.com"; const api = axios.create({ baseURL: apiBaseUrl }); api.defaults.withCredentials = true; // Store the token retrieved from the initial request let csrfToken = null; Vue.prototype.$api = api; Vue.prototype.$apiBaseURL = apiBaseUrl; export { axios, api, apiBaseUrl } export const fetchAllEvents = async function (context, payload) { try { // Step 1: Get the CSRF cookie setup const csrfResponse = await this._vm.$api.get('/sanctum/csrf-cookie'); // In a real scenario, check how Sanctum returns the token. // Often, the response headers or cookies contain the necessary info. // For demonstration, let's assume we need to read the token set in the cookie later, // but for this specific flow, we ensure the initial call succeeds. // Step 2: Make the protected POST request with explicit header (if needed) // If Sanctum relies purely on cookies, this step might be simpler: const response = await this._vm.$api.post('/api/website/event/all'); context.commit('setAllEvents', response.data.data); } catch (error) { console.error("Error fetching events:", error); } } ``` ### Best Practice: Leveraging Laravel's Middleware While manually managing tokens works, the most idiomatic way to handle this in a full-stack application is often ensuring that your API routes are set up correctly within Laravel, using Sanctum middleware. The discrepancy you are seeing between Postman and Axios strongly suggests an environment setup issue rather than a fundamental flaw in the backend logic, pointing towards how the client (Axios) handles cookie transmission across domains versus raw HTTP calls. For deep dives into modern PHP framework development and authentication mechanisms like Sanctum, exploring official documentation is always recommended. For more on building robust APIs with Laravel, check out resources from [laravelcompany.com](https://laravelcompany.com). ## Conclusion The 'token mismatch' error arises because the mechanism Sanctum expects for cross-origin requests (cookies) and the method Axios defaults to sending headers might not align perfectly in your specific setup. By ensuring `withCredentials = true` is set, confirming the initial token acquisition step succeeds, and understanding the interaction between cookies and request headers, you can resolve this. For complex authentication flows involving Laravel Sanctum, always verify that both client-side expectations and server-side middleware configurations are fully synchronized.