The canActivate function must be responsive to the true or false value of this.authService.isLoggedIn before proceeding

I am facing a problem with my app's routing functionality. When the user logs in with their Google email, I want the app to route to the home page: "". Everything seems to work fine except for the canActivate routeGuard. During the AuthLogin function, this.authService.isLoggedIn returns false after attempting to navigate to "". However, if I try to go to "" immediately after logging in, it works because this.authService.isLoggedIn shows true in the console.log. It appears that the canActivate function needs to wait until this.authService.isLoggedIn is updated. Do you have any ideas on how to resolve this issue?

Here are some relevant sections of code:

import { AuthGuard } from "./shared/guard/auth.guard";

const routes: Routes = [
  { path: "", component: HomeComponent, canActivate: [AuthGuard] },
  { path: "login", component: LoginComponent },
  { path: "results", component: ResultsComponent },
  { path: "profile", component: ProfileComponent },
  // Redirect to home if path does not match any defined routes
  { path: "**", redirectTo: "" },
];

auth.service:

// Returns true when user is logged in and email is verified
  get isLoggedIn(): boolean {
    const user = JSON.parse(localStorage.getItem("user"));
    return user !== null && user.emailVerified !== false ? true : false;
  }

  googleLogin() {
    return this.AuthLogin(new firebase.auth.GoogleAuthProvider());
  }

  async AuthLogin(provider: firebase.auth.AuthProvider) {
    try {
      const result = await this.afAuth.auth.signInWithPopup(provider);
      this.SetUserData(result.user);
      this.router.navigate([""]);
    } catch (error) {
      window.alert(error);
    }
  }

  SetUserData(user) {
    const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);
    const userData: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL,
      emailVerified: user.emailVerified,
    };
    return userRef.set(userData, {
      merge: true,
    });
  }

auth.guard:

import { AuthService } from "src/app/services/auth/auth.service";

@Injectable({
  providedIn: "root",
})
export class AuthGuard implements CanActivate {
  constructor(public authService: AuthService, public router: Router) {}
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    console.log(this.authService.isLoggedIn);
    if (this.authService.isLoggedIn !== true) {
      this.router.navigate(["login"]);
    }
    return true;
  }
}

Answer №1

Make sure to establish a Promise for the SetUserData function because it depends on a Firestore request being completed first. Once the promise has been fulfilled, proceed with navigating to an empty string.

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

"Production environment encounters issues with react helper imports, whereas development environment has no trouble with

I have a JavaScript file named "globalHelper.js" which looks like this: exports.myMethod = (data) => { // method implementation here } exports.myOtherMethod = () => { ... } and so forth... When I want to use my Helper in other files, I import it ...

Creating a specialized TypeScript interface by extending a generic one

Create a customized interface using TypeScript that inherits from a generic interface by excluding the first parameter from all functions. Starting with the following generic interface: interface GenericRepository { insertOne<E>(entity: Type<E& ...

Creating a TypeScript shell command that can be installed globally and used portably

I am looking to create a command-line tool using TypeScript that can be accessed in the system's $PATH once installed. Here are my criteria: I should be able to run and test it from the project directory (e.g., yarn command, npm run command) It must ...

Invoking the callback function within the containing scope in Typescript

I am facing an issue with my Angular component where I have a class that includes common services and functions. While passing some functions as callbacks, the scope is getting lost during execution. Let me demonstrate the problem through the code below: @ ...

What is the best way to emphasize when the path matches exactly with '/'?

Is there a way to highlight the path only when it exactly matches '/'? Currently, even on 'Page 2', the 'Home' link is still highlighted. Check out the plunker here .active { color: red; } <a routerLinkActive="active" r ...

Discover a Simple Trick to Enhance tsc Output: Unveil the Art of

When I work on a TypeScript project, I typically use the watch mode of the compiler: tsc --watch However, one issue I face is that it's challenging to identify errors in the output since they are displayed as plain text: Sometimes I don't even ...

Error message in TypeScript class extension: "TypeError: Object.setPrototypeOf expects an object or null, received undefined."

In my Ionic 3 application, I have the following code snippets: @Injectable() // I also tried without @Injectable and encountered the same error export class M_someClass { constructor () { } method1 () { console.log("method1 used") } } @Injectabl ...

A comprehensive guide to using Reactive Forms in Angular

I need help understanding how FormGroup, FormControl, FormArray work in Angular. The error message I'm encountering is: Type '{ question: FormControl; multi: true; choices: FormArray; }' is not assignable to type 'AbstractControl' ...

What is the best way to transform an array containing double sets of brackets into a single set of brackets?

Is there a way to change the format of this list [[" ", " ", " ", " ", " ", " ", " ", " ", " ", " "]] to look like [" ", " ", " &qu ...

Ensure to update outdated dependencies before installing them in an Angular project

Would it pose a risk to utilize a library with an outdated version of Angular compared to the project's current version? Is it advisable to employ npm i --force in such scenarios? ...

What's the deal with Angular query parameters and parentheses?

My Angular application has a routing structure that includes a query parameter. Here is an example: const routes: Routes = [{ path: '', component: DefaultComponent }, { path: ':uname', component: ProductDisplayComponent }]; Whe ...

Angular: extracting value from forkJoin nested within another observable's pipe

Here is the scenario that needs to be implemented: An API call is made which returns a response containing an array of objects. The objects are then mapped to another array of objects. For each item in this new array, another API call needs to be made. Th ...

Is Angular 5 ngx-permissions causing permissions to be deleted upon page refresh? Learn how to prevent this issue

https://i.stack.imgur.com/P1dr1.png https://i.stack.imgur.com/ktmB3.png Permissions Disappear after Page Refresh Is there a way to prevent permissions from being deleted upon refresh? ...

Incorporating mapboxgl-spiderifier into your Angular project: A step-by-step guide

I am currently working on an angular application that utilizes mapbox with the help of ngx-mapbox-gl. I am looking to integrate it with mapboxgl-spiderifier, but I'm facing an issue as it doesn't have typings and I'm unsure how to include it ...

Angular component showcasing the usage of a nested input-group

I have developed an input component and a datepicker component in Angular. The input component generates the appropriate input tag based on the type parameter, whether it's text, number, etc. Meanwhile, the date picker is another component that contai ...

Issues with the messaging functionality of socket.io

Utilizing socket.io and socket.io-client, I have set up a chat system for users and operators. The connections are established successfully, but I am encountering strange behavior when it comes to sending messages. For instance, when I send a message from ...

Issue with detecting window resize event in Angular 7 service

I have a unique service that utilizes a ReplaySubject variable for components, but strangely the WindowResize event isn't triggering. import { Injectable, HostListener } from '@angular/core'; import { ReplaySubject } from 'rxjs'; ...

``What is the process for retrieving an object array that has been stored in a session using

I have a new class definition: class ProductDetails { name!: string; price!: number; } I keep an array of these objects in the local storage like this: productList: Array<ProductDetails> = []; ... ... localStorage.setItem("CurrentProducts ...

Iterate over Observable data, add to an array, and showcase all outcomes from the array in typescript

Is there a way to iterate through the data I've subscribed to as an Observable, store it in an array, and then display the entire dataset from the array rather than just page by page? Currently, my code only shows data from each individual "page" but ...

When the route is changed, the system must execute a function to verify the authenticity of the token

When routing changes in Angular, I have a requirement to execute a function based on whether a valid token is set or not. Is there anyone who can assist me in achieving this task? In Angular 1, I used to accomplish this using $on. ...