Creating a universal timer at the application level in Angular

Is there a way to implement a timer that will automatically execute the logout() function in my authentication.service at a specific time, regardless of which page I am currently on within my application?

I attempted to create a timer within my AuthenticationService, but encountered an issue where the timer would be lost if I redirected to another page.

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 considered implementing the timer within app.component, but I only want to subscribe to the timer when the login function of the authentication service is called from the login form.

Answer №1

To enhance security measures, one effective method is to store the calculated logout time in localStorage during the login process. In the constructor, the timer can be started using the stored logout time or a default value if none exists.

@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']);

  }

}

Answer №2

I managed to resolve the issue by developing:

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},...
    ...
    ...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unlock the Full Potential of TypeScript: Seamless Export of Classes and Functions

In my AngularJS project, I have a separate JavaScript file where I declare prototype functions. Here's an example: function lastConv(){ this.item1="2" this.message="hello" ...... } lastConv.prototype.setupfromThread(data) { this.currentBox = dat ...

What is the best way to deploy a docker image from my computer to the office server?

I have an Angular project that has been Dockerized on my personal computer. I am now looking to deploy it on my company's server without having superuser permissions. What steps should I take to achieve this? ...

What is preventing me from setting a background image in Angular 13?

Trying a different approach based on advice from Stack Overflow, I attempted the following: <div [style.background-image]="'url(https://picsum.photos/200)'"></div> Unfortunately, this resulted in no effect and the image was ...

Firebase allows for the updating of an object within a nested array

Within Firestore, I have a Document that includes a property named "items" which is of type array. This array consists of ShoppingItem objects with the specified structure: export class ShoppingItem { id?: string; name: string; checked = false; } To ...

Is there a way to reverse the direction of the slider's track?

Our goal in the design is for users to select a value between 0 and 20, with the selected range being that value up to 20. Currently, Angular Material slider component highlights values from 0 up to the selected value as the active track. Is there a way to ...

What steps are involved in creating animations on angular.dev?

I'm trying to recreate the animation on angular.dev. Specifically, I want to create a zoom effect on the Angular logo when scrolling. However, I'm unsure how to achieve this effect. If you visit this page , you'll see exactly what I mean. ...

Ionic app: refresher functionality works in browser but not on iOS home screen app

I am currently developing a Progressive Web App (PWA) using Ionic, and I have implemented an ion-refresher in the app: <ion-content> <ion-refresher slot="fixed" (ionRefresh)="refresh()"> <ion-refresher-content pullingIcon="lines">& ...

Identifying misspelled names in shared resources textures during PIXI.js loading

Our game utilizes TypeScript, Pixi.js, VSCode, and ESLint. We maintain a dictionary of image files as follows: export function getAllImages(): {name: string, extension: string}[] { return [ {name: 'tile_lumber', extension: '.svg ...

Angular2 tubes sieve through hyperlinks within HTML content

As I receive HTML strings from an external source, my goal is to filter out all links that contain images, remove the href attribute, and replace it with a click event. I have attempted to achieve this using an Angular pipe, but so far I have only been suc ...

Having trouble retrieving an object property in HTML or TypeScript within an Angular framework?

export class ComponentOne { array_all_items: Array<{ page_details: any }> = []; array_page_details: Array<{ identifier: number, title: string }> = []; initial_item: Array<{ identifier: number, title: string }> = [ { ...

ng-deep is causing changes in sibling components

Facing a challenge with Angular Material Design as I discovered the need to utilize ng-deep to customize the styling of an accordion. The issue is that when I use this method, it affects another accordion in a different section which is undesirable. Is th ...

Primeng - Concealed dropdown values within a scrollable table header

Recently, I integrated Primeng p-table with a filter and frozen column feature (with one column being fixed while the others are movable). However, I encountered an issue with the select dropdown in the header. When I try to open the dropdown, the values a ...

Navigating Angular 2 v3 router - accessing the parent route parameters within a child route

My route is configured as /abc/:id/xyz The abc/:id portion directs to ComponentA, with /xyz being a nested component displayed within a router-outlet (ComponentB) Upon navigating to /abc/:id/xyz, I utilize this.route.params.subscribe(...) (where route is ...

Top method for continuously updating the position of DOM elements in Angular 2

Currently, I am in the process of developing a game using Angular (version 4). I understand that direct manipulation of the DOM is typically not recommended when working with Angular. However, for the particular functionality I'm trying to achieve, I& ...

Dynamically Disabling Form Control in Angular 2

There is a basic form with two form controls that initially have required validation. In addition to the form controls, there is a button in the template. When this button is clicked, it triggers a change in the behavior of the form group. Both form contr ...

Encountering an uncaughtException: Error stating that the module '....nextserverapphomelibworker.js' cannot be located while attempting to utilize pino.transport in Next.js

I recently set up a Next.js project with typescript using create-next-app. Opting for Pino as the logging library, recommended by Next.js, seemed like the logical choice. Initially, when I utilized Pino without incorporating its transport functionality, e ...

Adding a datepicker popup to an input field in angular2 with the format of YYYY-MM-DD hh:mm:ss is as simple as following

Can someone help me with adding a datepicker popup to an input field in Angular, using the format YYYY-MM-DD hh:mm:ss? I have tried the following code in my .html file but it doesn't seem to be working. <input [(ngModel)]="date2" ngui-datetime-pi ...

What is the approach of Angular 2 in managing attributes formatted in camelCase?

Recently, I've been dedicating my time to a personal project centered around web components. In this endeavor, I have been exploring the development of my own data binding library. Progress has been made in creating key functionalities akin to those f ...

How can I define types for (const item of entries) in Typescript?

I attempted for (const ElementType as element of elements ) {} or for (const ElementType of elements as element) {} However, neither of these options is correct. ...

Implementing OTP input using Material UI textfield

Is it possible to create an OTP input using the textfield component of material UI in a React TypeScript project? I've seen examples where people have implemented this with regular input fields, but I'm specifically interested in utilizing the te ...