Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSRF Token not refreshed when trying after logout from a Laravel session (only page refresh works) #2170

Open
PatrickCaneloDigital opened this issue Jan 7, 2025 · 2 comments

Comments

@PatrickCaneloDigital
Copy link

PatrickCaneloDigital commented Jan 7, 2025

Version:

  • @inertiajs/vue3 version: 2.0.0

Describe the problem:

Please excuse me if it's wrongly categorized or so...
Laravel/Jetstream/Fortify/Inertia/Vue3 App
When I logout and straight Login again, I get a 419 Error in the modal.
In order to get a new CSRF token I need to refresh the login page (or the homepage)
I am actually using Inertia without SSR
Also I get a 419 error right after the first login when I make axios POST calls, the 419 error does not appear on GET axios calls.
It seems to me that Inertia or vue somehow does not refresh the csrf token properly under certain circumstances thus displaying an older token which only gets refreshed with a page reload.

The logout calls
\Laravel\Fortify\Http\Controllers\AuthenticatedSessionController::class, 'destroy'
and then redirects to the NotAuthHomepage

Route::get('/', function () {
    return Inertia::render('App', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
})->name('web_home');

I am not sure where the CSRF caching occurs, because that home page already holds the old invalidated csrf token and not a new one

My Login is a vue component:

Route::get('login', function () {
    return Inertia::render('auth/cover-login');
})->name('login');

I have no meta csrf tag in my blade header, but I do have a
<script>window.Laravel = {csrfToken: '{{ csrf_token() }}'}</script>
for the app to work

Steps to reproduce:

Login To the App, immediately log out, and log in again (html shows the same csrf token even thought the session is correctly invalidated), as is proven by a simple page refresh

I can't fully understand where the csrf refresh should happen or if I could somehow refresh it from within the login vue (as that wouldn't hurt).
i prefer such a solution anytime compared to a automatic page refresh which at the moment seems my only choice.

@martinEtflais
Copy link

Try this $request->session()->invalidate() and $request->session()->regenerateToken() after logout...

@PatrickCaneloDigital
Copy link
Author

PatrickCaneloDigital commented Jan 17, 2025

Thx but the the Authenticate Session Controller should do that during logout (Session destroy)

I meanwhile also noticed that this problem appears only with POST requests but the GET requests get through without any issue.


public function destroy(Request $request): LogoutResponse
    {
        $this->guard->logout();

        if ($request->hasSession()) {
            $request->session()->invalidate();
            $request->session()->regenerateToken();
        }

        Log::debug('session invalidated');

        return app(LogoutResponse::class);
    }

But I get the problem anyway which makes me think of some caching inbetween the backend session and the frontend csrf token.
Because a simple page refresh makes everyything work, that shows me that it does work correctly. My assumption is that the session gets destroyed, but something in the frontend framework (like inertia render, inertia-vue or something) doesn't notice that until the next page refresh, and thus, a cached crsf token is used and not the regenerated one.

EDIT: I made a dirty hack meanwhile. As only axios post calls where affected by this unknown 419 error, i made a new post endpoint: check419. Oon the login page and after the login, check419 is called during setup, if a 419 is returned, then window location is reloaded. Like this the user experience is much better, as the 419 is caught before the user entered data, and even though a page refresh can be visible, better this than the user entering data and getting a 419 error for a unknown reason.but at least 419 errors on POST calls are prevented
So I have my dirty workaround

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants