There are three sections to Sanctum code depending on what you are doing. If it's an API, follow that section.
Laravel Sanctum generates new XSRF-TOKEN for stateful API Requests
I use Laravel Sanctum to authorize SPA application requests (NuxtJS). In general, I understood the idea with the /sanctum/csrf-cookie endpoint and am already sending a request using axios, which installs the XSRF TOKEN once before the user logs in, and then uses it for API methods while the session is alive and the XSRF-TOKEN itself is valid.
But I get the following result: Laravel generates a Set-Cookie XSRF-TOKEN header with each API request that I send before I go to /sanctum/csrf-cookie. For example: when the main page loads, 4 requests are sent (to receive data from the backend for rendering content). So each response to this request has a Set-Cookie XSRF-TOKEN header and overwrites it each time.
At the same time, the Set-Cookie response headers /sanctum/csrf-cookie look strange: it not only returns a new XSRF-TOKEN (as all API requests do for some reason), but also returns some_uuid=something similar to XSRF-TOKEN.
My front-end and backend work locally in docker-compose, so SANCTUM_STATEFUL_DOMAINS=localhost (although I tried to specify different values there, it didn't help).
I also tried specifying the FRONTEND_URL and changing the session settings. By the way, here they are (listed by "/" what I tried):
SESSION_DRIVER=cookie/redis/database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null/localhost
I use Laravel 11 and in my bootstrap/app.php specified by $middleware->statefulApi();; routes I tried has "api" middleware; axios config has withCredentials: true, withXSRFToken: true
What could be the problem and how to reduce the overhead of the backend (useless generation of a bunch of tokens for each request), as well as eliminate the problems with token synchronization on the front-end that this problem may cause?
Thank you in advance for your help.
any API request automatically passes CSRF authorization by sending a Set Cookie header in response.
Wrong. Routes in the web group (and stateful api routes) do use CSRF protection, but only for state-altering methods such as POST and DELETE, not "safe" methods such as GET.
Laravel includes the token in a cookie called XSRF-TOKEN so that front-end HTTP libraries like Axios can automatically discover it and add it as the X-XSRF-TOKEN header in future requests.
3rd party sites can't read the cookie and thus can't add the header. This is due to same-origin policy, which is also the reason why GET requests don't need to be protected against CSRF: a 3rd party site can't read the response. They also can't read POST, DELETE, etc. responses, but those are unsafe actions and must be blocked altogether.
You could, in theory, call any stateful GET route to get the token cookie prior to sending any unsafe requests. It just makes sense to use a route made specifically for that purpose.
As to why you get a different token each time, I'm not sure. You should get the same token every time as long as the session cookie is present on each request and you're not doing something that regenerates the session (e.g. login or logout). The token is just a single string in session, regenerating it has no actual overhead, and session data is written out at the end of each request anyway. So it won't affect performance.
P.S. Did I understand correctly that you receive a different token on every request? If you get the same token each time, then everything's working correctly. It's just a response header.
P.P.S. I think I see what's going on. Laravel encrypts cookies, so you should see a different set-cookie value on every request, even when the token doesn't change. If you're worried about the cookie being included in every response, and only want it done in the Sanctum endpoint, you can extend the VerifyCsrfToken middleware and customize it instead of using the off-the-shelf version. See this method in particular. But this is a total non-issue in my opinion.
Please or to participate in this conversation.