2

I am developing a new frontend using Vue to access my existing Laravel 7 app, which uses Sanctum for authentication.

The frontend sits on app.example.com, with the backend being moved to api.example.com. The CORS middleware and Sanctum are properly configured to allow app.example.com, and so far so good.

The GET to /sanctum/csrf-cookie looks fine, however, it doesn't seem to be actually setting the cookies, causing the subsequent request to the API to return a 419.

const config = { withCredentials: true };
const api = process.env.NODE_ENV === 'production' ? 'https://api.example.com' : 'http://localhost:9000';

axios.get(api + '/sanctum/csrf-cookie', config)
  .then(() => axios.post(api + '/login', data, config))
  .then(response => response.json())
  .then(response => { console.log('json', response); });

Console log: enter image description here

Response headers from /sanctum/csrf-cookie: response from /sanctum/csrf-cookie

No cookies are listed in devtools: enter image description here

UPDATE 1: Didn't notice this earlier; the warning icons next to each Set-Cookie in the response headers display "This set-cookie's Domain attribute was invalid with respect to the current host url."

Erich
  • 2,408
  • 18
  • 40

2 Answers2

4

Short answer: Ports should not be specified in cookie domain attributes.

Long answer: Laravel Sanctum uses the VerifyCsrfToken middleware to both send and verify the CSRF token, which uses session config values when adding the cookie to the response:

protected function addCookieToResponse($request, $response)
{
    $config = config('session');

    if ($response instanceof Responsable) {
        $response = $response->toResponse($request);
    }

    $response->headers->setCookie(
        new Cookie(
            'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
            $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
        )
    );

    return $response;
}

In config/session.php:

'domain' => env('SESSION_DOMAIN', null),

In .env:

SESSION_DOMAIN=localhost:8080

Cookies on the same host ARE NOT distinguishable by ports. Because I had specified the port in the cookie domain, the browser had flagged the cookie as having an invalid domain. Removing the port did the trick.

Erich
  • 2,408
  • 18
  • 40
  • Came here to say this was the answer to my question in the case it would help someone down the road. Extremely misleading because in the docs for sanctum it says "If you are accessing your application via a URL that includes a port (127.0.0.1:8000), you should ensure that you include the port number with the domain." Next to a big information box on https://laravel.com/docs/8.x/sanctum – Afs35mm Jan 16 '22 at 03:39
0

For me to solve the problem I changed my vue cli host which was 127.0.0.1:8080 to localhost:8080 in browser,and within axios the base url is now http://localhost:7000 which is for laravel api.

after that I then set SESSION_DOMAIN=localhost in .env laravel