I am trying to implement Auto Logout feature after 20minutes of inactivity of user. Therefore, I used @ng-idle/core npm package inside my project to set user idle after 20minutes of inactivity and to display popup which asks either logout or stay logged in for 60seconds which will get decremented after every second. In the start I had a problem with seconds mismatched issue while using multiple tabs in same browser window. To get rid of this issue I have implemented startInterval() and stored seconds into localStorage. Now, if I am using multiple window of same browser seconds in popup gets stuck after 2 times pressing stay logged in. Angular project window gets freeze after inactivity of the window of same browser. It would be helpful if anyone comes with a solution of my problem. Thanks
import { ChangeDetectorRef, Component, HostListener, OnInit } from "@angular/core";
import { MenuItem } from "primeng/api";
import { LoginService } from "./components/login/login.service";
import { Idle, DEFAULT_INTERRUPTSOURCES } from "@ng-idle/core";
import { DialogService } from "primeng/dynamicdialog";
import { Keepalive } from "@ng-idle/keepalive";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
providers: [DialogService],
})
export class AppComponent implements OnInit {
items: MenuItem[];
title = "maincontainer";
idleState = "NOT_STARTED";
countdown?: number = null;
lastPing?: Date = null;
showAutoLogout: Boolean = false;
showSpinner: Boolean = false;
setInterval: any;
// On tab close event reset idle event
// @HostListener('window:beforeunload', ['$event'])
// beforeunloadHandler(event) {
// this.reset();
// }
constructor(
public loginService: LoginService,
private idle: Idle,
private keepalive: Keepalive,
private cd: ChangeDetectorRef
) {
// Default timer started set to false in local storage
localStorage.setItem('timerStarted', 'false');
// set idle parameters
idle.setIdle(60); // how long can they be inactive before considered idle, in seconds
idle.setTimeout(60); // how long can they be idle before considered timed out, in seconds
idle.setInterrupts(DEFAULT_INTERRUPTSOURCES); // provide sources that will "interrupt" aka provide events indicating the user is active
// do something when the user becomes idle
idle.onIdleStart.subscribe(() => {
this.idleState = "IDLE";
idle.clearInterrupts();
this.checkLogin();
});
// do something when the user is no longer idle
idle.onIdleEnd.subscribe(() => {
if (localStorage.getItem("bearerToken")) {
this.idleState = "NOT_IDLE";
this.reset();
} else {
this.logout();
}
});
// do something when the user has timed out
idle.onTimeout.subscribe(() => {
this.idleState = "TIMED_OUT";
this.countdown = null;
// Removed event logout from idle timeout which we have manually handled in custom interval timeout
// this.showAutoLogout = false;
// this.logout();
});
// do something as the timeout countdown does its thing
idle.onTimeoutWarning.subscribe((seconds) => {
this.checkLogin();
this.showAutoLogout = true;
// Checked condition if interval is already not started trigger interval
if (localStorage.getItem('timerStarted') == "false") {
this.startInterval();
}
// this.countdown = seconds;
});
// set keepalive parameters, omit if not using keepalive
// keepalive.interval(15); // will ping at this interval while not idle, in seconds
keepalive.onPing.subscribe(() => {
this.lastPing = new Date();
// this.reset();
}); // do something when it pings
}
startInterval() {
// If interval is triggered timer started set to true and countdows set to 60 in local storage
localStorage.setItem('timerStarted', 'true');
localStorage.setItem('timerCountdown', JSON.stringify(60));
this.setInterval = setInterval(() => {
// Dedcuted timer countdown with 1 every second and set again in local storage to display in popup
let timerCountdown = +localStorage.getItem('timerCountdown') - 1;
localStorage.setItem('timerCountdown', JSON.stringify(timerCountdown));
// If timer countdown reach to 0 then action event logout and hide logout popup
if (localStorage.getItem('timerCountdown') == "0") {
this.showAutoLogout = false;
this.logout();
}
}, 1000)
}
// Made method to return timer countdown
get getCountdown() {
return localStorage.getItem('timerCountdown');
}
checkLogin() {
if (!this.loginService.isLoggedIn()) {
this.idle.stop();
window.location.href = "/login";
}
}
reset() {
// Cleared timer started, countdown from local storage and the interval
localStorage.setItem('timerStarted', 'false');
localStorage.setItem('timerCountdown', JSON.stringify(60));
clearInterval(this.setInterval);
// we'll call this method when we want to start/reset the idle process
// reset any component state and be sure to call idle.watch()
this.idle.stop();
this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
this.idleState = "NOT_IDLE.";
this.cd.detectChanges();
this.idle.watch();
this.countdown = null;
this.lastPing = null;
this.showAutoLogout = false;
}
ngOnInit(): void {
window.addEventListener('storage', function (event) {
if (event.key == "loggedIn") {
if (localStorage.getItem("loggedIn") == 'true') {
window.location.reload();
}
else {
window.location.href = '/login';
}
}
}, false);
// right when the component initializes, start reset state and start watching
if (this.loginService.isLoggedIn()) {
this.reset();
}
this.loginService.userLoggedIn.subscribe(() => {
this.reset();
});
this.loginService.userLoggedOut.subscribe(() => {
localStorage.clear();
window.localStorage.setItem('loggedIn', 'false');
window.location.reload();
});
}
logout() {
// this.loginService.userLoggedOut.emit();
this.showSpinner = true;
let token = localStorage.getItem("bearerToken");
let logoutData = {
loginId: localStorage.getItem("loginId"),
loginReportId: localStorage.getItem("loginReportId"),
};
if (!this.loginService.isLoggedIn()) {
this.loginService.userLoggedOut.emit();
return;
}
this.loginService.logout(logoutData, token).subscribe(
(data) => {
this.showSpinner = false;
this.loginService.userLoggedOut.emit();
this.idle.stop();
},
(error) => {
this.showSpinner = false;
this.loginService.userLoggedOut.emit();
this.idle.stop();
}
);
}
}