title: CSRF Token Mismatch with Laravel API using Digital Ocean Load Balancer with Sticky Session
body: <p>I am working on a project in Laravel 8 which I am now testing the deployment on production servers. I have set up 2 Digital Ocean Droplets that are behind a load balancer with Sticky Sessions enabled. I am attempting to login via a SPA app with a separate Laravel API so the middleware is configured for the api routes to be stateful API and perform CSRF validation. This works perfectly fine when I just hit a single droplet and bypass the load balancer but as soon as the load balancer is in use, I always receive a 419 CSRF Token mismatch.</p>
  <p>Everything I found on Google says that the session needs to be shared between servers, but I don't believe this is the case in this scenario. I have turned on sticky session with a cookie called DO-LB in the load balancer so all requests from the same session go to the same server, and I am tailing the Apache access log on both servers, and I can see all requests such as the get-csrf and the auth route (using Sanctum) both hit the same server so would I would still be getting a token mismatch.</p>
  <p>I am also using the cookie session driver.</p>
  <p><strong>UPDATE</strong></p>
  <p>I've found something a little strange, if I point my DNS to a singled droplet I see the X-XSRF-TOKEN is sent as a request header, but if I change DNS to point to the load balancer then X-xSRF-TOKEN is not sent as a request header. I am using Axios to send the request but I can't see how a load balancer can affect Axios</p>
  <p><strong>UPDATE 2</strong></p>
  <p>It looks like when I run it locally XSRF-TOKEN is not an HttpOnly cookie but when running it on production the XSRF-TOKEN is flagged as HttpOnly which from what I've read means its inaccessible from Javascript hence why Axios isn't sending it. I seem to have confirmed this by doing Cookies.get(&quot;XSRF-TOKEN&quot;) and printing the result, locally it prints the token to the console, but in production its undefined.</p>
  <p><strong>UPDATE 3</strong></p>
  <p>I updated my Apache configuration to override the headers as a test to remove the HttpOnly flag which seems to have done the trick, and I can now see when I log in, Chrome sends an X-XSRF-TOKEN in the request even though I still get a CSRF Token Mismatch.</p>
  <p>I've compared the string in the chrome cookie store with what is being sent in the X-XSRF-TOKEN and they both match so I don't understand why Laravel keeps returning me a mismatch and I am at a complete loss.</p>