Chrome not allowing Set-Cookie even from the same (sub)domain

3.4k views Asked by At

Here is my configuration:

SERVER

Laravel 8 application that uses Sanctum to provide access to REST API. It is configured to run on http://b8/

CLIENT

A separate Vue CLI 3.0 SPA that connects to the API using session-based cookie authentication method. I have configured Vue CLI Serve to run it at http://app.b8/.

PROBLEM

Chrome does not allow Set-Cookie operation even when both server and client are on the same domain. After going through several posts and articles, I have successfully run it in Postman, but the real Vue application that runs in the browser can't set Sanctum cookie and thus cannot login.

Here is my configuration:

.env

SESSION_DRIVER=cookie
SESSION_DOMAIN=.b8
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8080,127.0.0.1,127.0.0.1:8000,::1,b8,app.b8,app.b8:8080

vue.config.js

...
devServer: {
    proxy: "http://b8/api/v1", 
    host: "app.b8"
},

Login function in Vue application

async login(context, credentials) {
    axios.get('http://b8/sanctum/csrf-cookie').then(response => {
        axios.post('http://b8/login', credentials).then(response2 => {
          //successfully logged in.
        });
    });            
},

Error msg

The outer call for /sanctum/csrf-cookie route returns successfully and brings Sanctum cookie. However, Chrome thinks that the cookie is invalid for the current domain and therefore doesn't set it. Here is the Dev Tools pane's Cookies tab after the Sanctum token call returns (tooltip showing Chrome's complaint):

enter image description here

Since the cookie is not set, the following login call fails with a 419 error.

What am I missing here?

2

There are 2 answers

6
theovier On

I've recently set up the exact same thing (Laravel 8 backend with Sanctum + separate Vue Frontend) and it's working.

Your server side setup looks good. Please double-check that the frontend's IP is actually included in your SANCTUM_STATEFUL_DOMAINS - that caused the 419 error for me sometimes.

On the Vue side, make sure to that you enable the withCredentials in your axios instance, e.g.

const baseDomain = "http://localhost"
const baseURL = `${baseDomain}/api`

export default axios.create({
    baseURL,
    withCredentials: true,
})

If the provided suggestion does not help, I can further extend my answer by showing you more of my working backend code.

0
dotNET On

Finally got it working. For any future reader, here are the things:

  1. The first mistake that I was doing was to use a single word host name. It looks like Chrome (or Sanctum, not sure) wants you to have at least one period in the host name. So I changed it from b8 to b8.cod.
  2. You should keep same_site attribute set to lax. none is a rather dangerous value. Chrome now shows none as a potential issue.
  3. SESSION_DOMAIN should be set to .b8.cod with a leading period to support front-end subdomain, as correctly suggested by the documentation.
  4. All other things should be done as suggested in the question. axios must use withCredentials set to true.