2

I would like to have a timer that would fire logout() in my authentication.service at a specific time automatically no matter on which page I am in my application.

I tried creating a timer on my AuthenticationService but the problem is that if I redirect to another page.. this timer is lost.

authentication.service:

@Injectable()
export class AuthenticationService {
  ticks =0;
    timer :Observable<number>;
  constructor(private http: Http, private _JwtHelper: JwtHelper, private router: Router) {
  }

  isLoggedIn() {
    console.log('authentication service islogged in called ')
    let token = localStorage.getItem('token');
    if (!token) { return false; }
    else {
      return true;
    }
  }

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

           this.timer = Observable.timer(7000,1000);
    this.timer.subscribe(t=> {
        this.func(this);
    });


          return true;
        }
        return false;
      });
  }
func(t){
   this.logout();
   t.unsubscribe();
}
  logout(): void {

    localStorage.removeItem('token');
    this.router.navigate(['/login']);

  }

}

I thought about creating timer on app.component but then I want to subscribe to the timer only when login function of authentication service is called from login form.

SamuraiJack
  • 5,131
  • 15
  • 89
  • 195
  • What about creating a Timer service and inject such service in all Component pages? – Picci May 11 '18 at 07:28
  • You can create the timer in `AuthenticationService` and let it run. Then when calling `login` you just subscribe to it. – martin May 11 '18 at 07:29
  • You need the "timer" is always in your app. Two options: 1.- the app-component, 2.- a service that have ALL yours component – Eliseo May 11 '18 at 07:33
  • @martin I tried that. Didn't work. – SamuraiJack May 11 '18 at 09:48
  • @Eliseo I tried calling appcomponent function that sets timer , from login component but i am still facing same issue. As soon as I redirect it to some other page, timer is lost. – SamuraiJack May 11 '18 at 09:49
  • What do you mean by redirect? If you are redirecting to other page which is hosted on another server, then obviously you will lose the timer because the whole angular has been destroyed. Angular is a front end application. If you need a front end timer (and within angular), use a service. Other than that, you will have to resolve to use a server side timer. – CozyAzure May 11 '18 at 09:53
  • @CozyAzure I have set timer in app component which will redirect me to login page after n seconds. login--->Home(if i stay on this page my timer will throw me out to login after n seconds, which is perfect). But login--->Home--->SomeOtherPageofMyApplication (app component timer no longer seems to be working) – SamuraiJack May 11 '18 at 09:56
  • @CozyAzure Oh I got it now... If I enter a url in address bar (even if the url refers to another page of the same application, the whole angular instance gets destroyed.. If I just navigate from one page to another.. it would work – SamuraiJack May 11 '18 at 10:01

2 Answers2

0

You can store the calculated logout time in localStorage at the time of login, then in constructor you can start the timer from the localStorage time or your default value.

@Injectable()
export class AuthenticationService {
  ticks =0;
  timer :Observable<number>;

  constructor(private http: Http, private _JwtHelper: JwtHelper, private router: Router) {
    const logoutTime = localStorage.getItem('logoutTime') || Date.now() + 7000;
    this.startTimer(logoutTime);
  }

  isLoggedIn() {
    console.log('authentication service islogged in called ')
    let token = localStorage.getItem('token');
    if (!token) { return false; }
    else {
      return true;
    }
  }

  login(credentials) {
    return this.http.post('http://somthing/api/login/login',
      credentials)
      .map(response => {
        let result = response.json();
        if (result && result.token) {
          localStorage.setItem('token', result.token);
          localStorage.setItem('logoutTime', Date.now() + 7000);
          this.startTimer(Date.now() + 7000);
          return true;
        }
        return false;
      });
  }

  startTimer(time) {
    this.timer = Observable.timer(time);
    this.timer.subscribe(t=> {
      this.func(this);
    });
  }

  func(t){
      this.logout();
      t.unsubscribe();
  }

  logout(): void {

    localStorage.removeItem('token');
    localStorage.removeItem('logoutTime');
    this.router.navigate(['/login']);

  }

}
Vishnu Singh
  • 431
  • 4
  • 13
0

I solved it by creating:

CanActivateViaAuthGuard.service

@Injectable()
export class CanActivateViaAuthGuard implements CanActivate {

  constructor(private authService: AuthenticationService, private router: Router) {}

  canActivate() {         

        if(this.authService.isLoggedIn()==false ){
            this.router.navigate(['/login']);
            return false;
        }
        else{
            return true;
        }
  }
}

authentication.service:

 isLoggedIn() {

let token = localStorage.getItem('token');
if (!token) { return false; }
else {
  this.setTimeOutTimer();
  return true;
}
  }



setTimeOutTimer() {
    console.log('**setTimeOutTimer**')
    if(this.sub){
      this.sub.unsubscribe();
    }
 let expiry=this.currentUser.exp;

    this.timer = Observable.timer(1000, 1000);

    this.sub = this.timer.subscribe(t => {
      let timenow= moment().format('X'); 
      console.log(expiry + ' '+timenow );
      if(expiry<timenow){

        this.sub.unsubscribe();
      this.logout();

      }
    });
  }


get currentUser() {
    let token = localStorage.getItem('token');
    if (!token) return null;
    return this._JwtHelper.decodeToken(token);
  }

routes:

const routes: Routes = [
  {path: '', canActivate:[CanActivateViaAuthGuard], children:[
    {path:'home', component: HomeComponent},//,canActivate:[CanActivateViaAuthGuard]
    {path:'dummy', component: DummyComponent},...
    ...
    ...
SamuraiJack
  • 5,131
  • 15
  • 89
  • 195