2

I want application to automatically logout based on expiry token.

Angular Client Code:

login(credentials) {
    return this.http.post('http://something/api/login/',
      credentials)
      .map(response => {
        let result = response.json();
        if (result && result.token) {
          localStorage.setItem('token', result.token);
          return true;
        }
        return false;
      });
  }

Since the token conatains :

  "exp": 1526016179 // expiry time

I could perhaps do this in app.component which has <router-outlet></router-outlet>:

ngOnInit() {
    let token = localStorage.getItem('token');
   timer:DateTime = new Date(_JwtHelper.decodeToken(token).exp);
    if (timer && (Date.now() > timer)) {
      logout();       
    }
  }

But the problem with this approach would be that it won't logout automatically. It would require some sort of activity from user such as button click to fire ngOnInit() of app.component (which I am not even sure if it will fire everytime there is a button click anywhere in the website, probably not).

The application should automatically log out and redirect to login page as soon as the expiry time is hit.

Janith Widarshana
  • 3,213
  • 9
  • 51
  • 73
SamuraiJack
  • 5,131
  • 15
  • 89
  • 195
  • Do you think an interval in that component is inefficient? Thinking out loud here... – Carsten May 11 '18 at 05:57
  • Use interceptor service to identify token got expire then redirect to login page if token is expired – Soumya B. Athani May 11 '18 at 05:57
  • @SoumyaB.Athani That would still require a user action – Carsten May 11 '18 at 05:58
  • @Carsten I am new to angular. If there is a way to set a timer of somesort that would keep on checking if expiry timestamp has been hit. I am fine with that. – SamuraiJack May 11 '18 at 06:05
  • Best would be to send a request to a backend somewhere to keep your token alive. If the keepalive haven't been called for 15mins you can let the backend send a error the next time you try it with the same token and let Angular logout. – Swoox May 11 '18 at 06:09
  • @Swoox but that would again require some kind of user action. Imagine that the session is supposed to expire at 11:05am but since user did not make any server calls until 11:08am , he is still busy filling out a lengthy form in the webapplication. Now when he clicks on submit at 11:08am. He will be redirected to login. How annoying. – SamuraiJack May 11 '18 at 06:11
  • can you please let me know how did you achieve this atlast? @Arbaaz – Gayathri Apr 28 '19 at 11:38

3 Answers3

0

Use the timer(setInterval) to countdown till the next API call goes. If the current time is greater than the session expiry time, logout. If there is any new call goes to server, reset the timer.

This can be handled as a separate service which can be called on the httpInterceptor service.

0

To achieve this user must do a action on UI. I have done that as follows. But this happens only when user do a service call. Every service calls of my system call via this method.

public makeHttpCall(url, options): Observable<any> {

    if (options.auth) {
      if (!options.headers) {
        const token = this.CurrentUser.token
        const headers = new Headers();
        headers.append('Access-Control-Allow-Origin', '*');
        headers.append('Content-Type', 'application/json');
        headers.append('Authorization', 'bearer ' + token);
        headers.append('UserName', this.CurrentUser.username);
        options.headers = headers;
      }
    }

    return this.http.request(url, options).map(this.extractData).catch(this.handleError.bind(this)).pipe(
      tap( 
        data => {}
        ,
        error => {}
      )
    );

}


private extractData(res: Response) {
    const body = res.json();
    return body || {};
}

private handleError(error: Response | any) {
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
      if (error.status === 401 || error.status === 403) {
        // Here we can handle logout function of the system
        this.router.navigate(['logout']);

      }
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    return Observable.throw(errMsg);
 }

Hope this will help anyone.

Janith Widarshana
  • 3,213
  • 9
  • 51
  • 73
  • Like I said, I do not want to logout and redirect to login when user makes a service call.I want to redirect him to login as soon as expiry time is hit, even if her does not make server call – SamuraiJack May 11 '18 at 06:24
0
    const jwtToken = JSON.parse(atob(response.jwtToken.split('.')[1]));
    const expires = new Date(jwtToken.exp * 1000);
    const timeout = expires.getTime() - Date.now();
    setTimeout(() => this.logout(strategyName), timeout);

Use this response.JwtToken is the token from response after login. then this will logout as soon as the token expires using the timeout method.