Redirected when going from to via navigation guard - vue-router

I'm trying to protect my Vue components using the Vue router authentication guard.
Case scenario: unauthenticated user lands on home page ("/" route) and he's trying to access "/profile", but that's a private component, so he'll be redirected by the vue router to "/auth/profile", so he'll authenticate and then the Auth component will redirect the user to the "/profile" component, because he got its path in the URL.
That's my guard
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.private)) {
if (!store.getters.getUser) {
//console.log("PRIVATE - NOT authenticated");
next({ path: "/auth" + `${to.path}` });
} else {
//console.log("PRIVATE - authenticated");
next();
}
} else {
//console.log("NOT PRIVATE");
next();
}
});
Everything works as expected, but I get an error and it's annoying
Redirected when going from "/" to "/profile" via a navigation guard.

Somewhere in your code, after being redirected to "/profile", you are being redirected back to "/". And that is what the vue-router is complaining about.
So the problem resides in being redirected multiple times per action.
You'll want to make sure you only have one redirect per navigation action.

problem solved by replacing
next({ name: "Onboarding" });
with
router.push({ path: 'Onboarding' });

Reduce vue-router version to 3.0.7, or
follow code into your app.js or index.js, which one you import vue-router
example:
import Vue from 'vue';
import VueRouter from 'vue-router';
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {undefined
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
Vue.use(VueRouter);
...
#code

This could be because your other component (the one you are pointing to) is redirecting you back.

Related

Vue 3 Vue-router 4 Composition API - Calling router.push outside of component not working

In my Vue 3 project, i use the composition API of Vue and i have axios defined as a plugin in plugins/axios.js like this:
import axios from "axios";
import { useRouter } from "vue-router";
import { useErrorStore } from "../stores/error";
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
const errorStore = useErrorStore();
errorStore.state.errors.push(error.response.data.detail);
if (parseInt(error.response.status) == 422) {
const router = useRouter();
router.push({
name: "login",
});
}
return Promise.reject(error);
}
);
export default axios;
ANTICIPATED BEHAVIOR:
When the API call returns a 422 status, meaning the access token is invalid/ expired, the user shall be redirected to the login page.
PROBLEM:
router.push does not work, i am not redirected when the error occurs. And i am not getting any error message on the console either.
On the other hand, the errorStore as defined and accessed in the error case works just fine.
QUESTION:
How can i redirect the user to another route from within the custom axios plugin file?
Alternatively, is there a better/ more common way to achieve this?
Thanks for your help!

Vue-router doesn't redirect to page after checking if value exists

Good day. I am trying to create a guard to my Vue application that only redirects to a page if a value in a state exists (not null or undefined). However when I use beforeEnter I get a circular reference and it doesn't redirect me to the page. If I use beforeRouteEnter I am redirected normally but if I updated the page I am not redirect to the previous page. What exactly is wrong here method can redirect me to the page after checking a store state?
The method in the store is very simple and I simply save whatever comes from the api call in my state, which starts out as null. What exactly is wrong here?
import Vue from 'vue'
import VueRouter from 'vue-router'
import form'#/components/form.vue'
import values'#/components/values.vue'
import store from '#/store.js'
Vue.use(VueRouter)
const routes = [
{
path: '/',
component: form
},
{
path: '/values',
component: values,
beforeRouteEnter (to, from, next) {
guard(to, from, next)
},
}
]
const router = new VueRouter({
mode: 'history',
routes
})
const guard = function(to, from, next){
let info = store.getters.result
if(info){
next('/values')
} else {
next('/')
}
}
export default router
You have to use beforeEnter because beforeRouteEnter is the name of the in-component hook and will not work there. The reason you got a circular reference is that next('/values') redirects to itself. Change it to next() to tell the router to carry on with the current route with no redirect:
const guard = function(to, from, next){
let info = store.getters.result
if(info){
next()
} else {
next('/')
}
}

Vue router allways redirecting to error page

i am trying to setup a redirect when the user is not logged in. But when i do it like in my example the URL changes but i get This page could not be found from nuxt. The code is inside an login.js inside the plugins folder. Then i included this in the nuxt config like this.
plugins: [
'~/plugins/login.js'
],
And here is the actual code for handling redirecting
export default ({ app, store }) => {
app.router.beforeEach((to, from, next) => {
const loggedIn = store.state.account.loggedInAccount
if (!loggedIn) {
if (to.path !== '/redirect') {
next({ path: '/redirect' })
} else {
next()
}
} else {
next()
}
})
}
It looks like the routes are not mounted yet.
You should try to use middleware. It is the conventional way to implement the beforeEach function as mentioned by the official docs. You can read about it from here. If have access to the route object, store object and redirect function inside the middleware, so use redirect to direct to the other routes after validation.

Vue Router and Laravel Middleware

I want to add middleware in vue router, using laravel auth. If auth is checked then it should be allowed to open url otherwise retun back.
You can use vue-router Navigation Guards
as per your code i will try to add an example
{
path: '/',
component: HomePage,
beforeEnter: requireAuth
}
My navigation guard will be requireAuth as
function requireAuth(to, from, next) {
if (login) { //you local login check, you can either use vuex or local storage or cookies etc
next()
} else {
next("/login")
}
}

VueRouter, VueJS, and Laravel route guard

I wanted to hide a particular page of my application behind a layer of security (a simple passcode form that will send a request to the server for validation).
Based off the documentation of VueRouter, I figured a beforeEnter would be appropriate. However, I am not entirely sure how one would require a user to access a particular component, and then successfully enter a passcode before being allowed to proceed to this current route.
Does anyone have an example of this? I am having trouble finding anything similar.
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [
{ path: '/test/:testURL', component: require('./components/test.vue'),
beforeEnter: (to, from, next) => {
// somehow load another component that has a form
// the form will send a request to Laravel which will apply some middleware
// if the middleware successfully resolves, this current route should go forward.
}
},
];
const router = new VueRouter({
routes,
mode: 'history',
});
const app = new Vue({
router
}).$mount('#app');
Assuming you want to perform authentication only for selected components, you can go with using beforeEnter route guard. Use the following code.
const routes = [
{ path: '/test/:testURL', component: require('./components/test.vue'),
beforeEnter:requireLogin
},
];
function requireLogin(to, from, next) {
if (authenticated) {
next(true);
} else {
next({
path: '/login',
query: {
redirect: to.fullPath
}
})
}
}
Further, you can create a login screen and action in login component to redirect to given redirect parameter after setting authenticated variable to true. I recommend you to maintain authenticated variable in the veux store