DEV Community

Cover image for Implement Idle Timeout in Angular
Sarmitha Krishnagobal
Sarmitha Krishnagobal

Posted on

Implement Idle Timeout in Angular

In today's web applications, staying logged in on a website for an extended period, whether an hour or two, can pose security risks. During this time, background API calls might still be running, and if you're not actively using the site, someone else could potentially access it with your credentials. To mitigate these risks and reduce unnecessary server requests, it's crucial to monitor user activity, such as cursor movement or key presses. If the system detects inactivity for a specified duration, it can automatically log the user out. This feature, known as Idle Timeout, is essential for modern web applications.

Let’s dive into implementing idle timeout in Angular.

idleService.ts

import { Injectable } from '@angular/core';
import { interval, Observable, Subject, Subscription, throttle } from 'rxjs';

export class IdleService {
  private idleSubject = new Subject<boolean>();
  private timeout = 1200; //seconds
  private lastActivity?: Date;
  private idleCheckInterval = 600; //seconds
  private idleSubscription?: Subscription

  constructor() { 
    this.resetTimer();
    this.startWatching();
  }

  get idleState(): Observable<boolean> {
    return this.idleSubject.asObservable();
  }

  private startWatching(): void {
    this.idleSubscription = interval(this.idleCheckInterval * 1000)
    .pipe(throttle(() => interval(1000)))
    .subscribe(() => {
      const now = new Date();

      if (now.getTime() - this.lastActivity?.getTime()! > this.timeout * 1000) {
        this.idleSubject.next(true);
      }
    });
  }

  resetTimer(): void {
    this.lastActivity = new Date();
    this.idleSubject.next(false);
  }

  stopWatching(): void {
    if (this.idleSubscription) {
      this.idleSubscription.unsubscribe();
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This service monitors user activity and checks if the user has been idle for a specified duration. If so, it triggers an event through idleSubject

app.component.ts

import { inject, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { IdleService } from 'path-to-your-idleService';

export class AppComponent implements OnInit, OnDestroy {
private idleSubscription?: Subscription;
private idleService = inject(IdleService); 

ngOnInit(): void {
   this.idleSubscription = this.idleService.idleState.subscribe((isIdle) => {     
      if (isIdle) {
        console.log("user is idle");
        // Add logic for handling idle state, e.g., logging out
      } else {
       console.log("user is active");
     }
    });   
}

onUserAction(): void {
    this.idleService.resetTimer();
}

ngOnDestroy(): void {
    if (this.idleSubscription) {
      this.idleSubscription.unsubscribe();
    }
}
Enter fullscreen mode Exit fullscreen mode

Subscribes to the idle state and handles the user being idle or active. It also resets the idle timer on user interactions such as mouse movements, clicks, or key presses.

app.component.html

<div  
    (mousemove)="onUserAction()"
    (click)="onUserAction()"
    (keypress)="onUserAction()"
>
    <router-outlet />
</div>
Enter fullscreen mode Exit fullscreen mode

Captures user interactions to reset the idle timer whenever activity is detected.

Top comments (1)

Collapse
 
julgon2012 profile image
Julio 👹

In times when applications communicate with REST servers using tokens, JWTs, or others, these functions seem unnecessary.

Of course, if the server issues long-lived tokens, that is a flaw on the server's part.

Instead, I believe a good control mechanism should be implemented for the refresh token. Before reaching out to the server to refresh the access token, we could calculate the expiration of the refresh token and notify users that it has expired, or we could monitor the refresh token's expiration time and alert users a few minutes before it is about to expire, indicating that an action needs to be taken or the session will end.

It’s also important to consider that often the application in the browser is performing tasks and does not require communication with the REST server, which means the refresh token could expire, leading to a poor user experience by notifying them that their session is about to expire. In such cases, it would be essential to refresh the token without interrupting the user's task.