I have a project buit in laravel and vue I added forgot password reset system. the system sends email password reset link. but when I click the link it redirects to login page
the vue router navigation guard code is
router.beforeEach((to, _, next) => {
const isLoggedIn = isUserLoggedIn()
//console.log('can navigate', to, canNavigate(to))
if(to.name=='auth-reset-password'){
return {name:'auth-reset-password'}
}
if (!canNavigate(to)) {
// Redirect to login if not logged in
if (!isLoggedIn) return next({ name: 'auth-login' })
// If logged in => not authorized
return next({ name: 'misc-not-authorized' })
}
// Redirect if logged in
if (to.meta.redirectIfLoggedIn && isLoggedIn) {
const userData = getUserData()
next(getHomeRouteForLoggedInUser(userData ? userData.role : null))
}
return next()
})
how do I add exception to router.beforeEach of password reset
Related
I added this code in my router:
Router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login']
const authRequired = !publicPages.includes(to.path)
const user = <Utilisateur>JSON.parse(<string>localStorage.getItem('user'))
// console.log('user', user, authRequired, to, from, next)
if (authRequired && !user && to.path !== '/connexion') {
// console.log('redirect')
next({ name: 'connexion', query: { from: to.fullPath } })
}
next()
})
This warning message is displayed when the redirection is triggered, do you know how I can solve this problem?
|Vue Router warn]: The "next" callback was called more than once in one navigation guard when going from "/" to "/". It should be called exactly one time in each navigation guard. This will fail in production.
You should add else block that runs next():
Router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login']
const authRequired = !publicPages.includes(to.path)
const user = <Utilisateur>JSON.parse(<string>localStorage.getItem('user'))
// console.log('user', user, authRequired, to, from, next)
if (authRequired && !user && to.path !== '/connexion') {
// console.log('redirect')
next({ name: 'connexion', query: { from: to.fullPath } })
} else{
next()
}
})
for more details please check this
How to redirect to login page after an unauthorized request with Nuxt Auth Module in Universal Mode (when the token has expired or is no longer valid for exemple) ?
In my nuxt project, when I am logged in and my token deleted or expired, I am redirected only when I refresh the page. If not, my api calls return 403 errors, but I can still navigate in the secured pages, until I refresh.
Here is my Middleware :
export default function ({ $auth, redirect, route, store }) {
if (!$auth.user || !$auth.loggedIn || !$auth.user.role.includes('admin')) {
return redirect('/admin/login?r=' + route.fullPath.replace('/admin/', ''))
}
}
-- edit :
I Have fix my problem by changing my middleware to this :
export default async function ({ $auth, redirect, route }) {
await $auth.fetchUser()
if (!$auth.loggedIn || !$auth.user.role.includes('admin')) {
return redirect('/admin/login?r=' + route.fullPath.replace('/admin/', ''))
}
}
Is this the proprer way to do this?
Try this one
export default function ({ $auth, redirect }) {
if (process.client) {
if (!$auth.loggedIn || !$auth.user.role.includes('admin')) {
redirect('/admin/login')
}
}
}
Dont forget to add middleware to your layout or pages
I am using plugin
add in nuxt.config.js
plugins: [
'~/plugins/axios',
],
create in plugins folder, if not exist.. create manually plugins/axios.js
replace with this
export default function ({ $axios, redirect }: { $axios:any, redirect:any }) {
$axios.onRequest((config: any) => {
console.log('Making request to ' + config.url)
})
$axios.onError((error: any) => {
const code = parseInt(error.response && error.response.status)
if (code === 400) {
redirect('/400')
} else if (code === 401) { // Unauthorized
if (window.location.pathname !== '/login') {
window.location.href = "/login";
}
}
})
}
i am not using middleware
As a small Dev-Team, we are about to create our own social media website just for fun.
Our login process is handled with a jwt which is stored in localStorage.
async login( { commit }, user) {
commit('auth_request');
try {
const res = await axios.post('http://localhost:3000/api/v1/users/login', user);
if (res.data.status === 'success') {
const token = res.data.token;
const user = res.data.user;
localStorage.setItem('jwt', token);
commit('auth_success', { token, user } );
toast.success(res.data.message);
router.push({ path: '/' })
}
return res;
} catch (error) {
commit('set_errors', error.response.data)
toast.error(error.response.data.message);
}
},
However as soon as we change route we getting logged out.
router.beforeEach((to, from, next) => {
// check for user is logged in on route change
next();
})
How to prevent getting logged out on route change or page reload?
Well you are committing the token and it is saved in your localstorage so you can try this way so that your router knows that you are authenticated
This is a example router
path: "/dashboard",
name: "dashboard",
meta: { requiresAuth: true },
component: () => import("../views/Dashboard.vue")
I have a meta with requiresAuth: true so you can go to your router.beforeEach and create a if statement to check if there is a token if there is a token then stay logged in if not when trying to get into the Dashboard page take me to the login page.
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
if (window.localStorage.getItem("jwt")) {
next();
} else {
next({ name: "login" });
}
}else{
next()
}
});
We are doing a if stament where we get the token with window.localStorage.getItem("jwt") if there is a token in the localstorage then we can tell our router to stay logged in and navigate to the pages that has meta: { requiresAuth: true } if we dont have the token in localstorage take us to login page
I hope this helps you out or gives you an idea how to guard your routes. If you haven't solved the problem then just comment on the answer so we can solve the problem.
I have a navigation guard in place (main.js), which redirects certain routes if a condition is met:
router.beforeEach((to, from, next) => {
if (conditionMet)
next('/another-route');
else
next();
})
Now how can I know which route was redirected to /another-route?
The from object in, In-component navigation guard of /another-route doesn't point to the actual referrer, instead it points to the route which referred the redirected route. Sounds confusing?
In simple terms, If route A had a button which on click goes to route B and then route B is redirected to route C. The from object in C has details of A instead of B.
How do I know which route was actually redirected to C?
beforeRouteEnter(to, from, next) {
console.log(from);
/* */
next();
}
Any help would be appreciated.
You can't do it that way. But you can do a workaround by using query params in /another-route that points to route B. So it will be like /another-route?next=%2Froute-b. And after that, you can just use this.$router.redirect(this.$route.query.next)
This how I do it in my program if unauthorized user accessing some pages, e.g /customer/1. I use r for the query params.
beforeEnter: (to, from, next) => {
let access_token = Vue.cookie.get('access_token')
if (access_token == null) {
// user doesn't have access token, redirect to login
if (from.name !== 'login') { // prevent append /r if from is login page itself
next({ name: 'login', query: { r: to.fullPath } })
}
next({ name: 'login' })
} else {
// user has access token, user can open the page
next()
}
},
The link will become /login?r=%2Fcustomer%2F1
And in login.vue
onSubmit () {
this.submitting = true
let { username, password } = this
this.$api.POST('auth/login', { username, password })
.then(response => {
let { id, access_token } = response.data
this.setCookie(id, access_token)
this.$router.replace(this.$route.query.r)
})
.catch(error => {
if (error.response && error.response.status === 401) {
// show error that username or password is invalid
}
})
.finally(() => {
this.submitting = false
})
},
I have router which work with errors and can't understand how to fix it.
This global router which should check jwt token expiration and handle routing. Everything worked fine before adding some functionality like isActivated account. So now I need to check if User has token and if User account is activated.
1) If user has token it should make next() otherwise next("/login") (redirect)
2) If user has token but his account is not activated yet (first time login), it should redirect on Setup page next("/setup") until he submits some information.
So this is my guard
router.beforeEach((to, from, next) => {
const token = localStorage.getItem("token");
const tokenExp = parseInt(localStorage.getItem("tokenExp"))
const isActivated = localStorage.getItem("isActivated")
const now = new Date().getTime() + 129600000
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
console.log("first")
if (requiresAuth && !token) {
next('/login');
} else if (requiresAuth && token) {
if (now > tokenExp) {
axios.post("/user/t/r", token)
.then(e => {
const token = e.headers['authorization'].replace("Bearer ", "");
localStorage.setItem("token", token);
localStorage.setItem("tokenExp", (new Date().getTime() + 172800000).toString())
if (isActivated === 'true') {
next()
} else {
next("/setup")
}
})
.catch(e => {
localStorage.removeItem("token")
localStorage.removeItem("tokenExp")
localStorage.removeItem("fullName")
localStorage.removeItem("role")
next('/login')
})
} else {
console.log("second")
if (isActivated === 'true') {
console.log("third")
next();
} else {
console.log("fourth")
next("/setup")
}
}
} else {
next();
}
})
And this is my console.log with error when I login:
You are infinitely redirecting to /setup, You code on first run hits "fourth" then sends the user to /setup where that before call is run again and your infinite loop starts.
You need to stop calling next('/setup') or next('/login') if the user is already on that page.
You need to make use of router.currentRoute in order to check you are not going to redirect to page they are already on.
https://router.vuejs.org/api/#router-currentroute