I'm following Jeff's current Vue 2.0 series and come across a problem which I'm not sure the best way to tackle is.
The CSRF token is mismatched after a logout/login - meaning the user cannot login or logout again unless they refresh the page to load the new CSRF token injected by blade.
I'm assuming on the POST request to login/logout I will need to pass back the new CSRF in the response and update this client side - it just seems a bit nasty...
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
window.axios = require('axios');
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest'
};
And appears to be working fine. I've done a logout and login on another tab and it's still working on my original tab.
That doesn't help. Even we store csrf tokken in axios header, after it's expiration on server, our spa is unusable, unless we refresh the entire page and get a new csrf tokken from blade.
I think of some ways:
every 10 seconds, our spa requests new csrf tokken from backend, and renew axios header. this works, but user loses connectivity on other instances of the app, if he/she has opened multiple tabs. so, this approach is not practical.
server pushes new csrf tokken to user's sessions. this may work, but think of that extra work bothers me.
create an interceptor that request new token whenever the request failed by token mismatch and re run the failed request, i also set limit for this like 3 times, when it reach the limit it will refresh the window.
So the first approach with some improvements goes well if the route does not check the csrf token. Good point.
Api routes could be suitable. no extra middleware setup needed.
Thanks @bunnypro, but how is it different from not using token when everyone can get it?
Checking referrer is not a good idea, cause could be a mocked easily
Checking auth seems to work but again, we cannot login back the user that is logged out. we need to refresh the page again. Maybe I can exclude login route from CSRF protection, but it seems scary.
I already am able to detect mismatch token error. the question is what can i do to prevent that; or what to do when 419 happens.
in this situation every request to backend will be rejected. the only woking solution is to refresh the page and get the new token from blade. I hate to do that. users might have some unsaved form data on the page, that they might lose.
So, I was getting annoyed and did this TOKEN2 thing in my bootstrap.js file after i define window.axios, and the problem went away. Since I have a demo in the morning, that is nice. My question is, did this just magically remove all useful token checking? I'm not sure what this did exactly.
I also don't like that I have this problem in the first place. I'm using pagination. I get the first page, then the second page causes a token error, 1 second later, same axios call, same data, except "page: 2". Wasn't happening yesterday.
I approached this by modifying my logout controller to regenerate and return a new session token; then on the client/vue side, I updated my axios X-CSRF-TOKEN mapping with the new token. It works pretty effectively but hopefully someone has insight into why this might be a bad idea.
LoginController@logout
public function logout(Request $request) {
// Laravel default implementation
$this->guard()->logout();
$request->session()->invalidate();
// Added this
$request->session()->regenerateToken();
return $request->session()->token();
}