Reputation: 2262
I'm implementing a navigation guard for my Vue.js application, checking whether the user is logged in. I think the best way would be to ask Axios if it has a session cookie or not. Something like this:
router.beforeEach((to, from, next) => {
if (Vue.axios.hasSessionCookie())
next()
else
next(false);
}
Except, of course, hasSessionCookie()
doesn't exist, and I don't see anything like it in the docs. Is there a way, maybe by some extension?
Yes, I know I could store the login status in the VueX store. I don't think it's a good idea because the state would reset if the user, in his infinite wisdom, refreshed the page and thus reset the application. Another solution I have in mind is a backend endpoint where the app can "ask" if it's logged in. But that's also quite lame.
Upvotes: 2
Views: 2721
Reputation: 206
Tamás Polgár, you documented the same exact challenge I had with Vue; what to do with login if an unexpected browser event happens and the store is lost.
The Vue store:
The Vue store is meant to be a convenient location for an SPA to store such a flag (logged in or not), however, the store is completely erased and re-established with each Vue instance, which means a new browser window / tab, refresh, or other unexpected event that triggers a browser refresh.
So your approach describes an extra back-end call to quickly check the status, which is a legit and work-able solution IMO.
There are also two more potential solutions, the second of which of which I've implemented in my own SPA:
Two Other Solutions
1) Don't touch your back end code at all. Use vue-cookies to have the client browser set a cookie once a login has been established (this would be completely separate from the http-only cookie that the back-end API server needs).
This cookie should still exist after a browser refresh. I did not use (or try) this approach, however, as I didn't want to mess around with altering my front-end to check a local cookie each time I want to check for login status.
The front end code could use this cookie to figure out if the person is still logged in or not.
2) Another, separate approach is to short-circuit the normal back-end API check for authentication only for that specific route's controller, but not for any other route.
Here's how a 'short-circuit' on the back-end would work:
In the case of that specific route's controller method, have it first check for existence of the user in the request, and then return a 200 but with a status of "false" or some other variable which also appears in the success response.
It's counter-intuitive, but this gives the front end Axios call something to grab onto other than just a standard error response.
NOTE: I call it a "short-circuit" because if the back-end API route's controller method has a lot of code, making this check the FIRST thing it does will avoid the costly part of the call.
This approach works perfectly for my needs and doesn't require a new or secondary API call.
Upvotes: 0
Reputation: 2262
Thank you for all the tips. The right solution was the following:
/checklogin
route on the server before the Vue instance is created. This simply returns a 200 or a 401 status code depending on whether the user has a valid session or not. Then I set the VueX flag accordingly. This way the user can refresh the browser but VueX will still know if he's logged in or not.false
and redirects the user to the login page.I wrote an article on my Medium blog with details and snippets if anyone cares. https://medium.com/developer-rants/session-management-between-express-and-axios
Upvotes: 2
Reputation: 6853
Since it's a server-side cookie, you can't check it on client-side javascript, you need to make a HTTP request to your express server to check if session exists. Create a simple route on your express server like this:
app.get("/checkcookie", function(req,res) {
if (req.session.yourSessionVariableName) {
res.status(204).send();
} else {
res.status(401).send();
}
});
Then check on your vue navigation guard:
router.beforeEach(async (to, from, next) => {
const response = await axios.get("http://yourexpressbackend.com/checkcookie");
if (response.status === 204)
next()
else
next(false);
}
Upvotes: 1
Reputation: 54
You are going in the right direction but axios is a HTTP client and it has nothing to do with cookies neither do it care about cookies or storage.. so you need use a package like vue-cookies to set and get cookies.
Upvotes: 0