How do I check for token expiration and logout user?
Asked Answered
G

4

39

The user can logout himself when he/she clicks on the logout button but if the token is expired he/she cant logout because in my application, the token is used in both server side and front end. When user clicks on the logout button, the token from both server and browser is cleared if token is valid. There is a chance that when user does not log out and his/her token expires but is not being cleared in the browser. For addressing this situation, how do I check for token expiration every time the user visits in my app so if the token is expired, clear the token from the browser?

I tried in saga which watches in the background every time the user refreshes in the page or switch to another page. I don't think this is an efficient way. I reckon middleware comes into play.

function* loadInitialActions() {
  var dateNow = new Date();
  console.log(jwtDecode(token).exp < dateNow.getTime() - jwtDecode(token).iat);
  const token =
    JSON.parse(localStorage.getItem("user")) &&
    JSON.parse(localStorage.getItem("user"))["token"];
  if (
    token &&
    jwtDecode(token).exp < dateNow.getTime() - jwtDecode(token).iat
  ) {
    yield put(LOGOUT_SUCCESS);
  }
}

function* initialize() {
  const watcher = yield fork(loadInitialActions);
  yield take([INITIALIZE_ERROR, INITIALIZE_SUCCESS]);
  yield cancel(watcher);
}

function* rootSaga() {
  console.log("rootSaga");
  yield takeLatest(INITIALIZE, initialize);
}

So my question is how do I use the token expiration logic and logout user if token is expired from the middleware?

Grannia answered 8/7, 2017 at 4:11 Comment(0)
S
71

In my view middleware will be the best option.

You can do something like this

const checkTokenExpirationMiddleware = store => next => action => {
  const token =
    JSON.parse(localStorage.getItem("user")) &&
    JSON.parse(localStorage.getItem("user"))["token"];
  if (jwtDecode(token).exp < Date.now() / 1000) {
    next(action);
    localStorage.clear();
  }
  next(action);
};

You have to then wrap it in applyMiddleware

Saddleback answered 8/7, 2017 at 12:58 Comment(5)
@Saddleback where should I use this function , authguard ?Goldshlag
you can use it in store.js and that function should go inside applyMiddleware()Saddleback
"1000" is this milliseconds?Excruciate
i'm using store.getState(token) to get token, and i have persisted it into local storage with redux-persist. but when i call it it returns nullInvariable
@Saddleback what if I want to check before 1 min of token expiry? This j(wtDecode(token).exp - Date.now() / 1000) < 60000 is not workingClypeus
S
11
const parseJwt = (token) => {        
    const decode = JSON.parse(atob(token.split('.')[1]));
    console.log(decode);
    if (decode.exp * 1000 < new Date().getTime()) {
        logoutAction();
        console.log('Time Expired');
    }
};
Sulky answered 7/4, 2022 at 10:50 Comment(1)
Thanks Narek Grigoryan for sharing this useful code , it is working like a charmLoris
P
3

You need to wrap the Main component with a HOC. The HOC will validate the token and if OK allow the component to display. If the token is invalid, the login page is redirected to.

const authChecker = (Component) => {
  return class extends React.Component {
    state = {
      show: false;
    }

    componentWillReceiveProps(nextProps) {
      if (nextProps.children !== this.props.children) {
        this.checkAuth();
      }
    }

    componentDidMount() {
      this.checkAuth();
    }

    checkAuth() {
      Api.checkAuth()
      .then(result => {
        if (result.success) {
          this.setState({ show: true });
        } else {
          // logout since token expired
          API.logout();
        }
      });
    }

    render() {
      return this.state.show && <Component {...this.props} />
    }
  }
}

export default authChecker(Main);
Pod answered 8/7, 2017 at 4:53 Comment(3)
Is not the better way is to check in middleware?Grannia
Checking in middleware is another option, maybe better. The package redux-oidc takes this approach.Pod
I appreciate your kindness and your help. I could use the middleware but my token expiration logic is not working. I am checking the token is expired or not using this condition if (token && jwtDecode(token).exp < dateNow.getTime()) { next(action); localStorage.clear(); action.type = "Project/App/SHOW_TOKEN_INVALID_MESSAGE"; } but using this logic though i am currently log in, i am logged out because its says my token is expired. Can you help me with the token expiration logic using jwt-decode.Grannia
H
2

this.serverResponse.expires_inis the expiration time in seconds.

var tokenexpiration: Date = new Date();
tokenexpiration.setSeconds(new Date().getSeconds() + parseInt(this.serverResponse.expires_in))
console.log(tokenexpiration);

than you can save it to localStorage:

localStorage.setItem('expirationdate',tokenexpiration)

and with simple condition you can check whenever you need if the token was expired.

Hoe answered 10/10, 2018 at 7:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.