Reputation: 16863
I have a Vue.js SPA (app.example.com
) that communicates with a backend Laravel application (accounts.example.com
). Authentication is handled by the Laravel application - if an unauthenticated user visits the SPA, they are redirected to the Laravel app to log in and then redirected back to the SPA.
The Laravel application has a LoginController
that is using Laravel's built-in Illuminate\Foundation\Auth\AuthenticatesUsers
trait. Logging in works perfectly.
The problem I have is with logging out - I have a "Log out" button in the SPA that needs to log out the Laravel session.
In order to prevent denial-of-service via CSRF, Laravel's default logout route (in routes/web.php
-- Route::post('logout', [LoginController::class, 'logout'])
) only accepts POST
requests, not GET
requests. Additionally, the logout POST
must contain the CSRF token in the _token
field.
By default, I don't have access to the raw CSRF token in the SPA, only the encrypted version provided by /sanctum/csrf-cookie
, so I can't just create a form and have Vue.js submit it. I also can't use axios to do the logout for the same reason.
I tried to add another route (in routes/api.php
) like this so the same logout function will be called but the api
middleware group is applied instead of the web
middleware group:
Route::post('/logout', [\App\Http\Controllers\Auth\LoginController::class, 'logout']);
When I call this endpoint, I get an error:
Method Illuminate\Auth\RequestGuard::logout does not exist.
How can I get this logout to work without disabling CSRF protection or enabling GET
requets to logout?
Upvotes: 0
Views: 2015
Reputation: 16863
I found this discussion in the Laravel Sanctum repository.
Based on that, I changed my route in routes/api.php
like this:
Route::post('/logout', [\App\Http\Controllers\Auth\LoginController::class, 'logout'])
->middleware('auth:web');
This tells the logout API call use SessionGuard
instead of RequestGuard
, and resolves the issue.
Upvotes: 2