AuthGuard in Ionic 4 causing delay in page routing permissions

In my ionic 4 app, I store user information natively. The goal is to direct users to the Home Page if their information is already stored when they open the app. If not, they should be routed to the Login Page - pretty standard procedure.

However, the issue I'm facing is a brief display of the Login Page for about 500ms before redirecting to the correct page after reading the information. This inconsistency is not ideal.

I wish for the application to hold off on directing users to the Login Page or Home Page until it receives a response from the storage.

App.component.ts

  public initializeApp(): void {
    this.platform.ready().then((): void => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.authService.authState.subscribe((state: boolean): void => {
        if (state) {
          this.router.navigate(['home']);
        } else {
          this.router.navigate(['login-register']);
        }
      });
      this.permissionService.requestCameraPermission();
    });
  }

AuthService.service.ts

public readonly authState: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false)

  private _ifLoggedIn(): void {
    // check if user info is saved, indicating logged in state
    this.userService.getUserInfo().then((response: UserData): void => {
      if (response) {
        this.authState.next(true);
      }
    });
  }

  public isAuthenticated(): boolean {
    return this.authState.value;
  }

AuthGuard

export class AuthGuardService {
  private authService: AuthService;

  public constructor(authService: AuthService) {
    this.authService = authService;
  }
  
  public canActivate(): boolean {
    return this.authService.isAuthenticated();
  }
}

app-routing.module.ts

const routes: Routes = [
  {
    path: '',
    redirectTo: 'login-register',
    pathMatch: 'full',
  },
  {
    path: 'login-register',
    loadChildren: () => import('../pages/login-register/login-register.module').then(m => m.LoginRegisterPageModule),
  },
  {
    path: 'home',
    loadChildren: () => import('../pages/home/home.module').then(m => m.HomePageModule),
    canActivate: [AuthGuardService],
  },
];

If you require any additional information, feel free to ask. Thank you!

Answer №1

One issue that needs attention is the immediate return of a result by the BehaviorSubject upon initialization.

Another concern arises from the synchronous nature of the isAuthenticated() method, where the returned value may not align with the desired wait time for callers.

To address these challenges, consider employing a ReplaySubject and converting isAuthenticated() to an asynchronous function.

AuthService.service.ts

public readonly authState: ReplaySubject<boolean> = new ReplaySubject<boolean>(1)

  private _ifLoggedIn(): void {
    // Checks if user info is saved and updates logged in status
    this.userService.getUserInfo().then((response: UserData): void => {
        this.authState.next(!!response);
    }, (reason) => this.authState.next(false));
  }

  public async isAuthenticated(): Promise<boolean> {
    return this.authState.asObservable().pipe(take(1)).toPromise();
  }

Ensure that this.authState.next(false) returns a result rather than getting stuck indefinitely, handling scenarios like error 401 as "not logged in."

In addition, this.authState.next(!!response) offers a concise way to check for valid responses and handle cases of null or undefined, assuming your implementation of .getUserInfo() marks the user as not logged in under those conditions.

AuthGuard

export class AuthGuardService implements CanActivate {
  private authService: AuthService;

  public constructor(authService: AuthService) {
    this.authService = authService;
  }
  public async canActivate(): Promise<boolean> {
    return this.authService.isAuthenticated();
  }
}

Note the existing support for async operations in canActivate() and the inclusion of implements CanActivate for clarity.

For more insights on different types of Subject, refer to: Understanding rxjs BehaviorSubject, ReplaySubject and AsyncSubject

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

Typescript: Why Lines Are Not Rendering on Canvas When Using a For-Loop

What started out as a fun project to create a graphing utility quickly turned into a serious endeavor... My goal was simple - to create a line graph. Despite my efforts, attempting to use a for-loop in my TypeScript project resulted in no output. In the ...

Errors related to missing RxJS operators are occurring in the browser, but are not showing up in Visual Studio

Recently, I encountered a peculiar problem with my Angular4 project, which is managed under Angular-CLI and utilizes the RxJS library. Upon updating the RxJS library to version 5.5.2, the project started experiencing issues with Observable operators. The s ...

Retrieving a pair of data points from a Vue <select> event when it changes

I am facing an issue with a dropdown menu that is using an array with key:value pairs. I want the dropdown to only show values, but when a selection is made, I need to pass both the value and the key using the @change event. <select @change=" ...

Next-Auth | In cases where the user object contains an excessive number of items, the session request will be processed without

I will do my best to explain the issue that I am facing. Currently, I am using Strapi for backend and Nextjs for frontend development. To handle authentication, I have implemented NextAuth. [...nextauth].js: const options = { providers: [ Provider ...

Instructions for implementing personalized horizontal and vertical scrolling within Angular 9

I am currently working on an angular application where users can upload files, and I display the contents of the file on the user interface. These files may be quite long, so I would need vertical scrolling to navigate through them easily. Additionally, fo ...

The Ionic framework is showing an error that says "'LoginCtrl' is not defined as a function."

I encountered an issue while attempting to set up simple navigation in my ionic application. The error message I received was: "Argument 'LoginCtrl' is not a function, got undefined in the Ionic. What could be causing this problem?" Here is a sn ...

TypeScript types for d3 version 4

I am currently working on a d3 project and to simplify the development process and reduce errors, I decided to implement TypeScript. Using d3 v4, I initially faced issues with incorrect type definitions which led to errors like d3 not having a definition ...

Angular 17 | Angular Material 17.3.1: Problem encountered with Angular Material form field focus and blur event handling

I attempted to apply (blur) and (focus) effects to my mat-form-field input field, but it seems like they are not working properly on my system. Here is a code snippet that resembles what I am using: html file <form class="example-form"> ...

Tips for customizing the appearance of a specific mat-button component in an Angular project

In my Angular application, I have set up a scenario where users are presented with multiple choices through buttons. When a user clicks on a button, a specific component is displayed based on their choice. I am currently working on enhancing the styling of ...

Error: Astra connection details for Datastax could not be located

Currently, I am attempting to establish a connection to DataStax Astra-db using the cassandra-client node module. Below is an example of my code: const client = new cassandra.Client({ cloud: { secureConnectBundle: 'path/to/secure-connect-DATABASE_NA ...

Different ESLint configurations for mjs, js, and ts files

For my project, I've set up ESM (.mjs) files for server-side code, CommonJS (.js) for tooling, and TypeScript (.ts) for the client side. In VS Code, when I look at CommonJS files, I'm getting errors related to requires such as "Require statement ...

Is jQuery utilized by the bootstrap-grid system?

Finale: In our current setup, we are utilizing Angular 9, and like many frontend frameworks, there is a preference against incorporating other JavaScript libraries alongside the framework for manipulating the DOM. The Challenge: I am hesitant to include ...

The array used within the useEffect hook and the getCoordinates function appears to be distinct when printed with console

Utilizing GoogleMap API for Custom Location Display I have an imported array of JSON objects named data which includes an address property. The Google Maps API is used to retrieve coordinates from the addresses in order to generate custom markers displaye ...

Each property of an object has its own unique key, yet they all share the same data type

I have a single-use object with only three properties, all of which should be of the same type. The code below currently achieves this, but I'm curious if there is a more efficient way to declare the type for timingsObject: let timingsObject: ...

The issue of binding subjects in an Angular share service

I established a shared service with the following Subject: totalCostSource$ = new Subject<number>(); shareCost(cost: number ) { this.totalCostSource$.next(cost); } Within my component, I have the following code: private incomeTax: num ...

Broaden your interfaces by implementing multiple interfaces with Zod

Utilizing typescript, I am able to incorporate multiple interfaces interface Name { name: string } interface Age { age: number } interface People extends Name, Age { height: number } Is there a similar way to achieve this with Zod? What I attempted ...

Mastering the use of SVG icons in Angular 4+: A comprehensive guide

I have an icon.svg file with a collection of icons that I would like to use in my app, similar to how we display material icons. Does anyone have any ideas on how to include the file in the app and use these icons? I've tried looking for solutions a ...

What techniques can I use to adjust the size of an image through zooming in and out?

In my custom gallery component, the crucial code section looks like this: <Gallery> <Header> <img src={galleryIcon} alt='Galley icon' /> <h1>My Gallery</h1> </Header> ...

Code shared among several angular4 modules

Within my company, we are facing a challenge where there are multiple angular4 modules within a single Intellij project that contain duplicated common code. This includes Angular components, assets such as images and fonts, and dependencies like bootstrap ...

The PWA application is experiencing crashes on Safari following the recent IOS 17 update

Recently, I encountered an issue with my Angular app functioning as a PWA on my iPhone. Everything was working smoothly until the latest iOS 17 update. Now, the app crashes frequently and even when I clear the cache on Safari, it only works for a few min ...