Warn And Log Out User Due To Inactivity In Angular App
March 6, 2024 • Angular • Published By Josh • 4 minute read
Protecting sensitive data from unauthorized access is an important aspect to securing a web application. Implementing an automatic log out feature due to an inactive user can help with that. Let’s learn how!
Table of Contents
Package Installation
Install the @ng-idle/core package by running the following command:
npm install @ng-idle/core
Package Setup
In order to use the package, you need to provide it at the root of the application. Depending on your Angular setup and version, you’ll need to do one of the following:
app.module.ts
import { NgIdleModule } from '@ng-idle/core';
@NgModule({
providers: [
NgIdleModule.forRoot()
]
})
app.config.ts
import { importProvidersFrom } from '@angular/core';
import { NgIdleModule } from '@ng-idle/core';
export const appConfig: ApplicationConfig = {
providers: [
importProvidersFrom(NgIdleModule.forRoot())
]
};
Warn User With App Alert
When the user becomes inactive, let’s provide a warning with a countdown. I’m using Clarity’s alert component, specifically an app level alert since it appears at the top of the app. Make sure to place it in a location that appears no matter what page you’re on.
@if (inactiveUser) {
<clr-alert [clrAlertAppLevel]="true" [clrAlertClosable]="false" [clrAlertType]="'warning'">
<clr-alert-item>
<span class="alert-text">Logging out in {{ inactiveCountdown }} seconds due to inactivity.</span>
</clr-alert-item>
</clr-alert>
}
We wrap the alert in an if statement and only display it if inactiveUser is true. We’ll see how that variable is defined in a moment.
By the way, you can also use *ngIf on clr-alert instead of @if if you’re not yet on an Angular version that supports @if.
Handle Inactive User
Within your app component, let’s set up everything to handle an inactive user. Let’s start by importing what we need from the @ng-idle/core package.
import { DEFAULT_INTERRUPTSOURCES, Idle } from '@ng-idle/core';
Create a variable called idle for the idle service in the component constructor.
constructor(private idle: Idle) {}
Within the app component class, create a variable called inactiveCountdown, which will be of type number. This will count down the number of seconds before a user times out.
inactiveCountdown: number;
Create a variable called inactiveUser, which will be of type boolean. This will track whether the user is considered inactive or not.
inactiveUser: boolean;
You’re probably keeping track of when the user is successfully authenticated. This is the right time to start watching for when the user becomes idle or not.
if (authenticated) {
this.idle.watch();
} else {
this.idle.stop();
}
Now let’s create a private method called handleInactiveUser.
private handleInactiveUser() {
this.idle.setIdle(300);
this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
this.idle.setTimeout(15);
this.handleIdleStart();
this.handleIdleEnd();
this.handleTimeoutWarning();
this.handleTimeout();
}
- setIdle defines the number of seconds before a user is considered idle. So 300 seconds would be 5 minutes.
- setInterrupts defines what events will stop a user from being considered idle. We’ll use the default ones like mouse move, key down, etc.
- setTimeout defines the number of seconds before a user times out. The user will have 15 seconds to take action before they time out.
- handleIdleStart will listen for when the user is considered idle. We will set inactiveUser to true when this happens.
- handleIdleEnd will listen for when the user is no longer considered idle. We will set inactiveUser to false when this happens.
- handleTimeoutWarning will listen for the countdown. We will set inactiveCountdown to this countdown.
- handleTimeout will listen for when the user is considered timed out. We will log the user out at this point.
Let’s create those 4 methods mentioned above.
private handleIdleStart() {
this.idle.onIdleStart.subscribe(() => {
this.inactiveUser = true;
});
}
private handleIdleEnd() {
this.idle.onIdleEnd.subscribe(() => {
this.inactiveUser = false;
});
}
private handleTimeout() {
this.idle.onTimeout.subscribe(() => {
this.inactiveUser = false;
this.logOut();
});
}
private handleTimeoutWarning() {
this.idle.onTimeoutWarning.subscribe(countdown => {
this.inactiveCountdown = countdown;
});
}
All that’s left to do is call handleInactiveUser() in ngOnInit.
ngOnInit() {
this.handleInactiveUser();
}
Access your application and remain inactive for the number of seconds you defined. You should see the alert appear with the countdown. If you take any action the countdown will stop and the alert will disappear. If you time out, you’ll be logged out automatically!