Error: Redirected when going from "/pages/login" to "/dashboard" via a navigation guard - vue.js

Guys i don't know why im get this error when i try to login, console error after login is made:
Error: Redirected when going from "/pages/login" to "/dashboard"
via a navigation guard.
Im trying when i hit login to redirect me to /dashboard page after the validation is made but when i hit login it does nothing no redirect, and if i hit again the login button the redirect is made on dashboard page. Any solutions? Thanks!
loginJWT ({ commit }, payload) {
return new Promise((resolve, reject) => {
jwt.login(payload.email, payload.password)
.then(response => {
console.log(response.data)
// If there's user data in response
if (response.data.userDetails) {
// Navigate User to homepage
router.push(router.currentRoute.query.to || '/') // <- Here is the redirect after login
// Set accessToken
localStorage.setItem('accessToken', response.data.accessToken)
// Update user details
commit('UPDATE_USER_INFO', response.data.userDetails, {root: true})
// Set bearer token in axios
commit('SET_BEARER', response.data.accessToken)
resolve(response)
} else {
reject({message: 'Wrong Email or Password'})
}
})
.catch(error => { reject(error) })
})
}
In router js:
{
path: '/dashboard',
name: 'dashboard',
component: () => import('./views/Dashboard.vue'),
meta: {
rule: 'editor',
authRequired: false
},
beforeEnter: (to, from, next) => {
guard(to, from, next)
}
}
And the guard code that validate the token after each route:
const guard = function (to, from, next) {
// check for valid auth token
const token = localStorage.getItem('accessToken')
axios.post('http://localhost:8081/api/users/checkAuthToken', {tokn: token})
.then(function (response) {
if (response.status === 200) {
next()
}
}).catch(function (error) {
if (error.response && error.response.status === 401) {
alert('access neautorizat')
next('/pages/login')
localStorage.removeItem('userInfo')
localStorage.removeItem('accessToken')
}
})
}
beforeEach code:
router.beforeEach((to, from, next) => {
const publicPages = [
'/pages/login',
'/pages/register',
'/pages/forgot-password',
'/pages/comingsoon',
'/pages/error-404',
'/pages/error-500',
'/pages/not-authorized',
'/pages/maintenance',
'/callback'
]
const authRequired = !publicPages.includes(to.path)
const loggedIn = localStorage.getItem('accessToken')
if (authRequired && !loggedIn) {
return next('/pages/login')
}
return next()
})

First Set accessToken and Last Navigate User to homepage

Related

use firebase auth with vue 3 route guard

I have the needings to use firebase auth with vue router.
I have this simple guard, but I've noticed that sometimes the users will see for a while the pages also if they are not logged.
router.beforeEach( async (to, from) => {
onAuthStateChanged( getAuth(app), (user) => {
console.log(user, to.meta.requireAuth)
if( to.meta.requireAuth && !user ) {
return {
name: 'Signin'
}
}
})
})
I also have this kind of control inside my components, but I'm looking for something global to use to prevent unregistered users to see the app.
Any suggestion?
You can wrap the onAuthStateChanged in a Promise and make your before each an async function.
// in some global file
export async function getCurrentUser(): Promise<User | null> {
return new Promise((resolve, reject) => {
const unsubscribe = auth.onAuthStateChanged((user) => {
unsubscribe();
resolve(user);
}, reject);
});
}
// your router file
router.beforeEach(async (to, from, next) => {
if (to.matched.some((record) => record.meta.publicAccess)) {
next();
} else {
const currentUser = await getCurrentUser();
if (currentUser) {
next();
} else {
next({ name: "Login" });
}
}
});
// Your route object
{
name: "Login",
path: "/login",
component: () => import("#/views/authentication/Login.vue"),
}

how solve Avoided redundant navigation to current location: "/login". in vue?

Hi everybody i'm trying to make login page and redirect to home page ('/')
When i'm logging i haven't errors in console i can see the error using vue devtools
ERROR VUE DEV TOOL
End of navigation
/login
02:27:19.124
guard:afterEach
failure:Avoided redundant navigation to current location: "/login".
status:❌
from:/login
fullPath:"/login"
path:"/login"
query:Object (empty)
hash:""
name:"login"
params:Object (empty)
matched:Array[1]
meta:Object (empty)
redirectedFrom:undefined
href:"/login"
to:/login
fullPath:"/login"
hash:""
query:Object (empty)
name:"login"
path:"/login"
params:Object (empty)
matched:Array[1]
meta:Object (empty)
redirectedFrom:Object
href:"/login"
this is my login's method
methods:{
async submitForm(user){
const userForm=new FormData();
userForm.append("username", this.username);
userForm.append("password", this.password);
await this.$store.dispatch("auth/login", userForm).then(
()=>{
const user = localStorage.getItem('user')
console.log(user) //to check if i logged, in console get undefined but if try localStorage.getItem('user') i got the user.
this.$router.push('/')
}),
(error)=>{
console.log(error)
}
}
}
ROUTES
const router = createRouter({
history: createWebHistory(),
scrollBehavior() {
return { top: 0 }
},
routes,
})
{
path: '/',
name: 'dashboard',
component: () => import('#/views/Dashboard.vue'),
children: [
{
path: '',
name: 'home',
component: () => import('#/views/dashboard/Home.vue'),
},
....
router.beforeEach((to, from, next) => {
const publicPages = ['/login'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
// trying to access a restricted page + not logged in
// redirect to login page
if (authRequired && !loggedIn) {
next('/login');
} else {
next();
}
});
auth.service
class AuthService {
login(user) {
let dator={
access_token: '',
user:{}
}
console.log('AUTHSERVICE-->\n'+user)
return axios
.post(API_URL + 'login/access-token', user)
.then(response => {
console.log(response.data.access_token)
if (response.data.access_token) {
dator.access_token=response.data.access_token
localStorage.setItem('token', JSON.stringify(dator.access_token))
axios.get(API_URL + 'users/me/', { headers: authHeader() })
.then(response =>{
localStorage.setItem('user', JSON.stringify(response.data))
dator.user=response.data
})
}
return dator;
});
}
auth.module VUEX
import AuthService from '../services/auth.service';
const token = JSON.parse(localStorage.getItem('token'));
const user = JSON.parse(localStorage.getItem('user'));
const initialState = token && user
? { status: { loggedIn: true }, token,user }
: { status: { loggedIn: false }, token:null, user: null };
export const auth = {
namespaced: true,
state: initialState,
actions: {
login({ commit }, userForm) {
console.log(userForm)
return AuthService.login(userForm).then(
datologin => {
console.log('datologin',datologin)
commit('loginSuccess', datologin);
return Promise.resolve(datologin);
},
error => {
commit('loginFailure');
return Promise.reject(error);
}
);
},
if after login i force the '/' in the browser the page work. So i don't know where is my bad.
Sorry for noob error. The problem was in second request with axios so i refactor this part and now work
async asyncLogin(user){
let uservuex={
access_token: '',
user:{}
}
try{
const token = await axios.post(API_URL + 'login/access-token', user)
uservuex.access_token = await token.data.access_token
localStorage.setItem('token', JSON.stringify(uservuex.access_token))
const me = await axios.get(API_URL + 'users/me/', { headers: authHeader() })
uservuex.user= await me.data
localStorage.setItem('user', JSON.stringify(uservuex.user))
}catch(error){
console.log(error)
}
return uservuex
}

how to make route redirect to login if user is not loggedIn in vuex

What is the problem in guard route the condition if(!store.getters.loggedIn) is always return false. If no token I can to go very routes. can anyone tell me the solution plz .
my expectation is want to make guard route when user is not login and there is not token from api it will redirect to login page and if user is not loggin the user can only go to login page.
in store.js
import http from '#/axiosAPI/axios.js';
import router from '#/route/index';
const auth = {
namespaced: true,
state:{
Users: [],
Errors: [],
Success:"",
Loginerror:"",
Token: localStorage.getItem('access_token') || null,
},
getters:{
loggedIn(state){
return state.Token !== null;
}
},
mutations:{
LOGIN_ERROR(state,erro){
state.Loginerror = erro;
},
AUTH(state,token){
state.Token = token;
},
UNAUTH(state){
state.Token = null;
}
},
actions:{
loginUser({commit}, formData){
http.post("/login",formData).then((response)=>{
if(response.data.status === 'success'){
//set token
const token = response.data.token;
localStorage.setItem('access_token',token);
localStorage.setItem('user',response.data.user);
commit('AUTH',token);
router.push({name:'Dashboard'});
router.go();
}else{
commit("LOGIN_ERROR",response.data.message);
}
})
.catch((error)=>{
if(error){
commit('UNAUTH');
localStorage.removeItem('access_token');
localStorage.removeItem('user');
commit("GET_ERRORS",error.response.data.errors);
}
});
},
logoutUser({commit}){
http.post("/auth/logout").then((response)=>{
if(response.data.status === "success"){
commit('UNAUTH');
localStorage.removeItem('access_token');
localStorage.removeItem('user');
router.push({name:'Login'});
window.location.reload();
}else{
commit("LOGIN_ERROR",response.data.message);
}
})
.catch((error)=>{
if(error){
commit("GET_ERRORS",error.response.data.errors);
}
});
},
deleteUsers({commit},userID){
http.delete("/auth/delete/"+userID).then((response)=>{
if(response.data.status === 'success'){
commit("SUCCESS",response);
router.go(); //to reload page
}
else if(response.data.status ==='fail'){
commit("GET_ERRORS",response.data.message);
}
})
.catch((error)=>{
console.log(error.response);
});
}
},
}
export default auth
in route.js
Even if no token i can go to every route and the condition in guard route is always return false
import route from '#/route/index.js';
import store from '#/store/modules/auth.js';
route.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
if(requiresAuth){
if(!store.getters.loggedIn){ //i think the problem is here
next({name: 'Login'});
}else{
next();
}
}else{
next();
}
});
One way you can check if a user is logged in is to check directly whether there is a token in localStorage.
route.beforeEach((to, from, next) => {
const token = localStorage.getItem('access_token')
//if not logged in, redirect to Login page
if (!token) next ({ name: 'Login' });
//else continue
else next();
});

Why is my VueJS Login reloading despite catch being called?

I have the following code. The catch() is getting called, I can see the toastr alert. However immediately after the page reloads. Any idea why?
signIn() {
this.$store
.dispatch('auth/login', this.credentials)
.then(() => {
this.$toastr.s('You are successfully logged in')
this.$router.push({ name: 'About' })
})
.catch(() => {
// this.$toastr.e('You are successfully logged in')
this.$toastr.e('Please check the form')
})
}
Login Code:
login({ commit }, data) {
commit(types.AUTH_ERROR_CHANGE, null)
// console.log(process.env.VUE_APP_API_URL);
const url = process.env.VUE_APP_API_URL + '/authentication_token'
return new Promise((resolve, reject) => {
axios
.post(url, data)
.then(response => {
commit(types.AUTH_UPDATE_TOKEN, response.data)
resolve(state)
})
.catch(() => {
commit(types.AUTH_ERROR_CHANGE, 'Incorrect username or password')
reject(state)
})
})
},``
Sorry all, the problem was elsewhere completely.
I had an axios interceptor from previous code:
axios.interceptors.response.use(
data => {
store.commit('general/' + types.LOADING_STOP)
return data
},
error => {
store.commit('general/' + types.LOADING_STOP)
if (
error.response &&
error.response.status &&
error.response.status === 401
) {
// window.location.href = '/login'
}
return Promise.reject(error)
}
I had an old location.href there

Vuejs ssr check user is authenticated for each request

I’m using this ssr boilerplate for my app, https://github.com/vuejs/vue-hackernews-2.0
I don’t know how to implement logic for checking is user authenticated for each user’s page request, I’m using cookies for storing user's token
I looked that router can handle request before render component:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
// isLoggedIn()
// .then(response => response.json())
// .then(json => {
// console.log(json[0])
// next()
// })
// .catch(error => {
// console.log(error)
// next()
// })
const x = true
if (!x) {
next({
path: '/signin',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
return router
}
But here is problem, router starting to use this code in client-side and in server-side, which in my case a little bit incorrect.
How to send request for is user authenticated only once, or in client-side or in server-side?
Answering on my issue, next approach - is what I searched, this vue router middleware will check user, before sending other requests(in my components methods like asyncData), then put user's info into store:
// router/index.js
export function createRouter (cookies) {
const router = new Router({ ... })
router.beforeEach((to, from, next) => {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (to.matched.some(record => record.meta.requiresAuth)) {
if (router.app.$store) {
router.app.$store
.dispatch('FETCH_CURRENT_USER', cookies)
.then(next)
.catch(() => next('/signin'))
} else {
next()
}
} else {
next()
}
return router
}
// store/actions.js
export default {
FETCH_CURRENT_USER: ({ commit }, cookie) => {
const values = {
credentials: 'include',
headers: {
'Content-Type': 'application/json',
Origin: FRONTEND_HOST,
Cookie: cookie
}
}
return fetch(`${API_HOST}/api/v1/users/me`, values)
.then(handleStatus)
.then(handleJSON)
.then(json => commit('SET_CURRENT_USER', json))
}
}