2

So I have a SPA set up to authenticate with a Laravel application using Laravel Sanctum's suggested cookie-based authentication.

I'm having a bit of a hard time understanding the security surrounding using the cookie-based sessions however. From what I can see, if I authenticate with my Laravel application, I receive the session in a cookie in my storage client-side. All well and good, and expected.

However, if I then request some data, and then proceed to log out of my application, then send a request for data with a previous request in the network tab, I get the data returned, despite having previously attempted to unauthenticated with Laravel. This seems to me like Laravel has not invalidated the previous session.

Take the following scenario:

  • Send GET to /sanctum/csrf-cookie
  • Send POST to /auth/login with above cookie (and auth creds)
  • Send GET to /auth/user with above cookie (receive auth user back)
  • Send POST to /auth/logout with above cookie
  • Session should be invalidated
  • Send POST to /auth/user (using first cookie, or resend first /auth/user request in network tab)
  • I get the /auth/user data back, after attempting to logout

I can't fathom that Laravel would allow this to be a thing, so I'm somewhat confident there's a step I'm missing somewhere.

The following is what I have in my logout controller at present; I've tried with and without the web guard, with and without the session invalidate calls. Is there a "right" way of doing this, or is this just some flaw in the way cookie-based sessions work; are they only stored client-side? Should I be able to request data again and be authenticated?

Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
Nick Davies
  • 573
  • 5
  • 15

1 Answers1

3

I ran into the same issue when using the cookie session driver and Auth::guard('web')->logout(); in my logout web route. While I couldn't find any documentation to support this, I believe it's because the cookie is only stored client side in this configuration.

Changing the driver from cookie to database solved the issue by keeping the session data server side, the logout function is able to invalidate it and previously issued cookies will no longer work.

To make this change we can follow the instructions from the Laravel docs:

When using the database session driver, you will need to create a table to contain the session records. [...] You may use the session:table Artisan command to generate this migration.

php artisan session:table
 
php artisan migrate

Once this is done update the SESSION_DRIVER option in your .env file from cookie to database

  • Thanks, that does look to be the case. It just seems highly insecure to allow only the client to be responsible for the session data and nothing protecting it from Laravel's side. I know the cookie does have HTTP only set as true so it would be inaccessible from Javascript and thus XSS but still. – Nick Davies Jun 26 '22 at 16:31
  • 1
    From my tests the `cookie` and `database` session drivers seem to function the same way from the client's perspective as the client still gets the same cookies, the only difference is they are tracked within the database and thus can actually be invalidated server side. I agree it seems like odd behavior to desire or have as the default, but the fix is easy enough. Hopefully my answer helps you solve this. – GlitchWitch Jun 26 '22 at 17:18
  • 1
    Absolutely, thanks for the help. I think I was just looking for someone to confirm my concerns with the approach, so I've switched back to using the database driver for now. Cheers – Nick Davies Jun 26 '22 at 20:45