4

I am working on a web-app using node.js and vue.js, I am doing authentication and maintaining session using jwt and passport.js using passport-jwtstrategy

I have done all the things from creating jwt to protecting routes all the things now my issue is while generating jwt I am passing expiresIn:3600 so I want to auto-logout my user from Ui and remove token from localStorage once it has been one hour

On decoding my jwt I am getting

 {
  "name": "Dheeraj",
  "iat": 1571896207,
  "exp": 1571899807
}

So how can I get the real-time when to logout

In my auth.js vue store file my logout code when user clicks on logout is

logout({ commit }) {
        return new Promise((resolve, reject) => {
            localStorage.removeItem('jwt-token')
            localStorage.removeItem('user-name')
            commit('setAuthUser', null)
            resolve(true)
        })

    },

In the same file, I have a method getAuthUser which is running whenever a page is loading or reloading to check to protect rout and guestUser

getAuthUser({ commit, getters }) {
        const authUser = getters['authUser']
        const token = localStorage.getItem('jwt-token')
        const isTokenValid = checkTokenValidity(token)
        if (authUser && isTokenValid) {
            return Promise.resolve(authUser)
        }

        commit('setAuthUser', token)
        commit('setAuthState', true)
        debugger
        return token


    }

So how can I logout once my token is expired Anyone out here please guide me how can I logout once the token is expired

Edit

In my router.js file

router.beforeEach((to, from, next) => {
store.dispatch('auth/getAuthUser')
    .then((authUser) => {
        const isAuthenticated = store.getters['auth/isAuthenticated']

        if (to.meta.onlyAuthUser) {
            if (isAuthenticated) {
                next()
            } else {
                next({ name: 'login' })
            }
        } else if (to.meta.onlyGuestUser) {
            if (isAuthenticated) {
                next({ name: 'welcome' })
            } else {
                next()
            }
        } else {
            next()
        }
    })

})

from my auth file I am calling get authUser which I have already mention above

for checking token validity I am using this code

function checkTokenValidity(token) {
if (token) {
    const decodedToken = jwt.decode(token)
    return decodedToken && (decodedToken.exp * 1000) > new Date().getTime()

}
return false

}

but it returns false when I am on login page and there is no token there but once I am loged in it shows null

My global api file

    import axios from 'axios';

export default () => {
    let headers = {
        'cache-control': 'no-cache'
    };
    let accessToken = localStorage.getItem('jwt-token');

    if (accessToken && accessToken !== '') {
        headers.Authorization = accessToken;

    };
    return axios.create({
        baseURL: 'http://localhost:8086/',
        headers: headers
    });
}
  • You can use `beforeEach()` in router.js and validate the jwt token expiration time – Yashu Mittal Oct 24 '19 at 07:54
  • @YashuMittal hey I am using that `beforeEach()` to check authUser, My problem is I am not able to get the time from token, can you help me with flow please check my edit –  Oct 24 '19 at 08:03
  • I am not sure why you need the time, if the user try to move to some other page and the token is already experied, it should show an error or return false. – Yashu Mittal Oct 24 '19 at 08:05
  • @YashuMittal my token is on localstorage so on logout I am destroying the token once the token is expires it is throwing error but I cannot put logout code in each page and checking if `responce===401` then logout my `getAuthUser` it is running every time when page is load or reload , So how can I do it in this method, Please check my edit –  Oct 24 '19 at 08:08
  • @dheerajkumar you don't need to put logout code everywhere to check the response code. you can add a global http interceptor to handle that. – Max Peng Oct 24 '19 at 08:11
  • @MaxPeng can you show me some code, I have also a base-api.js file where I am passing the header as `'Bearer'+token` –  Oct 24 '19 at 08:15
  • In this function getAuthUser() if there is no valid token you should do the logout stuff. – Yashu Mittal Oct 24 '19 at 08:16
  • Like: Redirect to login page – Yashu Mittal Oct 24 '19 at 08:17
  • I don't think Bearer token will help here. – Yashu Mittal Oct 24 '19 at 08:18
  • @YashuMittal the main thing is how would I check token is valid or not? I have written a function to check validity but it is showing null when token expires –  Oct 24 '19 at 08:19
  • @dheerajkumar there is an example of global interceptor https://stackoverflow.com/questions/37228087/vue-js-interceptor – Max Peng Oct 24 '19 at 08:20
  • How about? ` if (jwtDecode(token).exp < Date.now() / 1000) { next(action); localStorage.clear(); } ` – Yashu Mittal Oct 24 '19 at 08:23
  • @YashuMittal I have tried this it says jwtDecode is undefined is this a package? –  Oct 24 '19 at 08:25
  • @MaxPeng I have updated my global file but how to do it inside is way different in my code then the link you had provided –  Oct 24 '19 at 08:27
  • var axiosInstance = axios.create({ baseURL: 'http://localhost:8086/', headers: headers }); axiosInstance.interceptors.response.use((response) => { if(response.status === 401) { alert("You are not authorized"); } return response; }, (error) => { if (error.response && error.response.data) { return Promise.reject(error.response.data); } return Promise.reject(error.message); }); – Max Peng Oct 24 '19 at 08:44
  • @MaxPeng now to call api using axios I am doing it like `axios().post('/api/v1/users/1', data)` is there any thing needs to be changed in my auth.js store file? and the code you have given should I put it inside export function? –  Oct 24 '19 at 09:01
  • @dheerajkumar only needs to change the export function. – Max Peng Oct 24 '19 at 09:05
  • @MaxPeng How would my base-api.js looks like? where should I put your code sir? can you just show me how my full code of base-api.js should looks like because it throws error –  Oct 24 '19 at 09:06

1 Answers1

3

Refer to the axios documentataion: https://github.com/axios/axios

import axios from 'axios';

export default () => {
    let headers = {
        'cache-control': 'no-cache'
    };
    let accessToken = localStorage.getItem('jwt-token');

    if (accessToken && accessToken !== '') {
        headers.Authorization = accessToken;

    };
    const instance = axios.create({
        baseURL: 'http://localhost:8086/',
        headers: headers
    });

    instance.interceptors.response.use((response) => {
        if(response.status === 401) {
             //add your code
             alert("You are not authorized");
        }
        return response;
    }, (error) => {
        if (error.response && error.response.data) {
             //add your code
             return Promise.reject(error.response.data);
        }
        return Promise.reject(error.message);
    });

    return instance;
}
Max Peng
  • 2,879
  • 1
  • 26
  • 43
  • hey it doesn't help I have given expiry time of 20 sec so when I am refreshing after that it is not going in any condition not here `if(response.status === 401) {` neither here `(error) => {` –  Oct 24 '19 at 09:25
  • After you refresh the page, you may need to seed a request to the backend to verify the token. Otherwise, the interceptor will not take effect. – Max Peng Oct 24 '19 at 09:36
  • yup there are api's which are running on page refers and at backend I am checking them with passport also –  Oct 24 '19 at 09:39
  • Ok, this is for reacting when token has expired and user is doing post/get via axios using expired token. How to deal with page refresh, or when user just enters a url directly into browser? – farahm Nov 07 '20 at 20:43
  • Refresh the page and enter URL directly basically are the same, the browser will load the HTML, CSS, Javascript first then send the AJAX request to the server. – Max Peng Nov 08 '20 at 03:52