I have followed a number of posts' guidance on Stack Overflow and other websites about setting up Vue routes to check for user authentication. The setup I now have does essentially work correctly (for each route, the user authentication status is checked, and redirected to the login page if necessary) but there is a small issue in that just before the user is redirected, the standard Nuxt/Vue 404 page screen flashes up momentarily.
This is an example of each route that requires user authentication that I have in router.js:
...
{
path: '/question/:id/comments',
name: 'comments',
component: page('Comments.vue'),
meta: {requiresAuth: true},
beforeEnter: (to, from, next) => {
guard(to, from, next);
}
},
...
And here is my guard() function that checks the user authentication and then redirects them with next() as required:
const guard = function(to, from, next) {
axios.get(process.env.apiUrl + 'check-auth').then(response => {
if( to.matched.some( record => record.meta.requiresAdmin ) ) {
if( response.data.is_moderator !== 1 ) {
next({ path: '/' });
} else {
next();
}
} else if( to.matched.some( record => record.meta.requiresAuth ) ) {
if( !response.data.id ) {
next({
path: '/login',
params: { nextUrl: to.fullPath }
});
} else {
next();
}
} else {
next();
}
});
};
Many articles online suggested using localStorage to check the user authentication but this doesn't work in router.js (presumably because its server side and not client side) but I got around this using a Laravel API call with Axios to check it instead.
If anyone can shed any light on why the 404 screen flashes up first before the redirect? Going to the routes directly works fine, so I am guessing it must be something to do with the next() method.
It's probably waiting for an axios response for a small amount of time. You could use async/await approach, and wait for the axios response before navigating to a route. Route would look like this:
async beforeEnter: (to, from, next) => {
await guard(to, from, next);
}
And in your guard you would do something like this:
const guard = async function(to, from, next) {
const response = await axios.get(process.env.apiUrl + 'check-auth')
if( to.matched.some( record => record.meta.requiresAdmin ) ) {
...
Rest would be the same. This would wait for a response before navigating to a route.