Search code examples
phplaravelcookiessingle-page-applicationsanctum

Laravel Sanctum and Cookie-Based Session Security


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();

Solution

  • 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