'419 error in Laravel after logging out and back in (multiple tabs)
I have two tabs open in my Laravel application.
I click "logout" in one tab. Then I click "logout" in the second tab. This second logout used to give a 419 error, but I added it to the exclusion list in the VerifyCsrfToken middleware. I don't see why I would need CSRF protection for logging out.
But, now I have a different issue.
After logging out in both tabs, both of them are sitting on the login page. Now if I try to log back in from the first tab, I get a 419 error. From the second tab, the login works correctly.
How can I handle this? I don't want to show an error to the user when they click "login", it's bad user experience. I also don't want to exclude the login route from CSRF protection.
Solution 1:[1]
Considerations
in this Answer i am naming your browser opened tab as Tab A and Tab B
just consider this following rules:
- your browser have one session active for a domain at a time (access with session_id cookie).
- client-side : every opened tab can have a CSRF Token in its forms,header,....
- server-side : only one csrf token are held in session variable.
- on every post request, the client and server token should be match, else a 419 error rises.
Necessity of CSRF Protection for logout
no there is no need for preventing CSRF Protection in logout route, since its not a Resource changing route. and it was good that you except=['logout'] from CSRF Protection.
Happening Scenario
1
first you have opened tab A and B they are logged in and shared same session and token
tab A - session 1 - token x tab B - session 1 - token x
2
click on tab A logout. it will cleared session from server . redirect back to login page. in login page, client request to server, made him a new session and token.
tab A - session 2 - token y tab B - session 2 (cookie with session_id are for domain) - token x (client: is presented in tab / removed from server because it was in session 1)
since there is no session 1 in server-side which holds token x so the tab B token mismatched the server y token
3
sending logout on tab B .
if you send logout with csrf enabled. middleware sends you 419 because there is mistmached between token x on client anb b on server .
if its Exempt from csrf , it **clears session ** on server side and redirect client to login page, after redirection server make a new session with a new csrf token for tab B.
i suppose you exempt csrf protection on logout route and continue with second scenario.
tab A - session 3 - token y tab B - session 3 - token z
as you see server has session 3 with token z . so tab A mistmatched
Conclusion
as you saw there was some reasons for this mistmatches:
- session (cookie) are browser scope but tokens are tab scope
- user do something on a tab that make other tab to have a session which mistmaches its form token
so as you see The Prevention Solution has get appeared :
if users want to:
- have multiple tab opend
- Logout (re-creating session) on one tab
- continue with other opened tab/forms (a refresh could solve the problem)
Solution
you have to make The Session and token Scope Sync
there are 2 solutions :
make token browser-scope : with using XSRF instead of CSRF which achievable with using SPA client side frameworks. (preferable)
make session page-scope :
change logout functionality to not to clear session just clear the response session_id
make session tracking with hidden input (which has its downwards itself) (obsolote)
I Recommend to use Single Page Application Frameworks for Client Side
Solution 2:[2]
Simple and easy Solution to avoid from "419 page expired":
- Go to middleware.
- VerifyCsrfToken.php
- Create new method handle
use Closure;
use Illuminate\Support\Facades\Auth;
public function handle($request, Closure $next)
{
if($request->route()->named('logout')) {
if (!Auth::check() || Auth::guard()->viaRemember()) {
$this->except[] = route('logout');
}
}
return parent::handle($request, $next);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Abilogos |
| Solution 2 | ouflak |
