Angular User Session Timeout example step by step

This functionality let the user know that their session is about to expire and that they would be logged out if they didn’t take action. I have written this functionality in Angular for my latest application. 

If you are new to Angular 6 then read my article about Setting up Angular 6 step by step before jump to this article to get handy in Angular 6.





Dealing with timers in Angular can be significantly different when using React components and subscriptions. The basic premises remains the same, though. We’ll have a service with a timer that will provide a Subject to which consumers of the service can subscribe. A React Subject provides an easy mechanism to trigger a “next” subscription to alert consumers that the timer has expired.
 
  import { Injectable } from '@angular/core';  
 import { Observable, Subject, Subscription, BehaviorSubject} from 'rxjs/Rx';  
 @Injectable()  
 export class IdleTimeoutService {  
   private _count: number = 0;  
   private _serviceId: string = 'idleTimeoutSvc-' + Math.floor(Math.random() * 10000);  
   private _timeoutSeconds: number = 5;  
   private timerSubscription: Subscription;  
   private timer: Observable<number>;  
   private resetOnTrigger: boolean = false;  
   public timeoutExpired: Subject<number> = new Subject<number>();  
   constructor() {  
     console.log("Constructed idleTimeoutService " + this._serviceId);  
     this.timeoutExpired.subscribe(n => {  
       console.log("timeoutExpired subject next.. " + n.toString())  
     });  
     this.startTimer();  
   }  


 
The timer variable is our actual Observable that we use internally. You can see below that we use React’s timer observable. We’ll have it trigger in five seconds and subscribe to it. Once it is triggered, we call our handler. The “startTimer” method sets up our subscriptions.

  public startTimer() {  
   if (this.timerSubscription) {  
     this.timerSubscription.unsubscribe();  
   }  
   this.timer = Observable.timer(this._timeoutSeconds * 1000);  
   this.timerSubscription = this.timer.subscribe(n => {  
     this.timerComplete(n);  
   });  
 }  
 public stopTimer() {  
   this.timerSubscription.unsubscribe();  
 }  
 public resetTimer() {  
   if (this.timerSubscription) {  
     this.timerSubscription.unsubscribe();  
   }  
   this.timer = Observable.timer(this._timeoutSeconds * 1000);  
   this.timerSubscription = this.timer.subscribe(n => {  
     this.timerComplete(n);  
   });  
 }  

Our timer handler will call the “next” method on our Subject to which others may be subscribed. This provides a nice eventing mechanism. Optionally, we can reset the timer after trigger. However, for most of my use cases, I’ll be resetting this manually.

   private timerComplete(n: number) {  
     this.timeoutExpired.next(++this._count);  
     if (this.resetOnTrigger) {  
       this.startTimer();  
     }  
   }  
 }  
To consume the service, the IdleTimerService is injected as needed. Then, we can subscribe to its exposed/public Subject. The basic subscription is show in the code snippet.

  ngOnInit() {  
   this.startCounter();  
   this._idleTimerSubscription = this.idleTimeoutSvc.timeoutExpired.subscribe(res => {  
    var modalPromise = this.dialogSvc.open("Session Expiring!", "Your session is about to expire. Do you need more time?",  
      true, "Yes", "No");  
    var newObservable = Observable.fromPromise(modalPromise);  
    newObservable.subscribe(  
      (res) => {  
        if (res === true) {  
          console.log("Extending session...");  
          this._status = "Session was extended.";  
          this.idleTimeoutSvc.resetTimer();  
          this.startCounter();  
          this.changeRef.markForCheck();  
        } else {  
          console.log("Not extending session...");  
          this._status = "Session was not extended.";  
          this.changeRef.markForCheck();  
        }  
      },  
      (reason) => {  
        console.log("Dismissed " + reason);  
        this._status = "Session was not extended.";  
        this.changeRef.markForCheck();  
      }  
    );  
   });  
  }  
In the demo app below, I have a secondary counter within a component, also using an RxJS timer, to illustrate that the subject does emit to subscribers every five seconds. I then use a dialog service to display a modal. The modal itself returns a promise result. This simulates the concept of extending a user’s session if they click “Yes” or not extending it if they click “No.”

While I didn’t illustrate it, this becomes the starting point for hooking into Http interceptors to access a heartbeat API, or some other endpoint, to extend the user’s session at the server level (or cookie refresh). All in all, timers and observable s are pretty fun to play around with in Angular.

Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.

Comments

Popular posts from this blog

Implement Logging in CSV file using Nlog in .net core MVC application- part 2

Implement Nlog in .Net core MVC application part 1

Devexpress Datebox date formatting in angular 6 with example

Disable backspace key using Jquery