What causes Angular guards to execute before the ngOnInit lifecycle method?

In my application, I have a function called checkAuth within the ngOnInit method of the app.component.ts file. This function checks the localStorage for a token and if the token is valid, the authService logs you in.

Additionally, there is an AuthGuard set up on the /profile route to verify if you are logged in.

The issue arises when clicking a link in the navbar works fine, but going directly to a link causes the AuthGuard to run before my checkAuth function, resulting in a false return.

Where should I position my checkAuth function to ensure it works correctly? Or should I make changes to the AuthGuard or app.component?

Here is the code for the AuthGuard:

@Injectable({
  providedIn:'root'
})
export class AuthGuard implements CanActivate, CanActivateChild {

  constructor(private auth:AuthService, private router:Router) {
  }

  canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
    console.log(this.auth.isAuth)
    console.log(this.auth.isLoggedIn())
    if (this.auth.isLoggedIn()){
      return of(true)
    } else {
      this.router.navigate(['/login'])
      return of(false)
    }
  }

  canActivateChild(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
    return this.canActivate(route, state)
  }
}

Code snippet from app.component:

ngOnInit() {
    if (localStorage.getItem('token')){
      this.auth.checkAuth().subscribe(
        (data) => {
          console.log(data)
          console.log(this.auth.isAuth)
        }
      )
    }
  }

Snippet showcasing the checkAuth function in AuthService:

checkAuth():Observable<UserDto>{
     return this.http.get<UserDto>(`/api/user/refresh`, {withCredentials:true, observe:'body', responseType:'json'})
        .pipe(
          tap(
            (data) => {
              localStorage.setItem('token', data.accessToken)
              this.setAuth(true)
              this.setUser(data.user)
            },
            (error) => {
              console.log(error)
            }
          )
        )
  }

Answer №1

To ensure that checkAuth runs before the guard, it needs to be implemented as a guard itself and placed before the existing guard in the activation sequence. For example:

canActivate: [CheckAuthGuard, AuthGuard]
.

The current flow is as follows:

Scenario 1 - Accessing /profile by clicking on the navbar

  1. You navigate to the application's root component
  2. Any guards assigned to the root route are executed
  3. The root component initializes and triggers AppComponent.ngOnInit(), which includes checkAuth()
  4. You click on the navbar link to access the /profile route
  5. Guards specific to the profile route are activated

Scenario 2 - Directly accessing /profile via URL

  1. You reach the application's root component, but this time it directs you to the /profile route
  2. Any guards associated with the profile route are invoked
  3. The root component and its child components initialize, triggering their respective ngOnInit() methods

As seen in scenario 2, the guard takes precedence over ngOnInit and checkAuth. It is recommended to add console.log statements throughout your application to track the sequence of events more effectively.

In essence, guards execute before the component rendering process begins, so it is crucial to refactor checkAuth into a guard for seamless operation.

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

Propositional Properties within the Interface

I have a question about interfaces: Currently, I am working on a dynamic component that needs to change based on the page it's on. The structure of my interface is as follows: interface Props { heading: string; description: string; signUp?: boolean; ...

Unable to establish a connection to 'X' as it is not recognized as a valid property

Trying to implement a Tinder-like swiping feature in my Angular project, but encountering an error stating that the property parentSubject is not recognized within my card component. Despite using the @Input() annotation for the property, it still fails to ...

Is there a way to retrieve a specific type from a union-based type by using a generic function in Typescript?

When working with my API, I have noticed a consistent pattern where it returns either a specific type or a TypeScript type called BadResult, as shown below: type Result1 = CreatedPersonResult | BadResult; type Result2 = CreatedRoleResult | BadResult; To s ...

Learn the process of creating an Angular CLI project following a switch to webpack by utilizing the ng eject command

After experiencing problems with some libraries, I made the switch from Angular CLI to webpack. Within my webpack.config.js file, I manually added a few scripts. Now, how can I compile the angular project without reverting back to CLI? In the past, I util ...

Leveraging IntersectionObserver to identify the video in view on the screen

Our Objective I aim to implement a swipe functionality for videos where the URL changes dynamically based on the ID of the currently displayed video. Challenges Faced Although I managed to achieve this with code, there is an issue where the screen flashe ...

Utilizing npm/buffer package within a TypeScript module

I'm interested in implementing this NPM package: https://www.npmjs.com/package/buffer I'm unsure about how to convert this line of code into typescript: var Buffer = require('buffer/').Buffer Could you provide me with the correct code ...

Making sure a value is a specific string in TypeScript

Here is what I currently have: type AppDisplay = "MainMenu" | "Game" | "GameOver"; interface AppState { appDisplay: AppDisplay } const initialAppState : AppState = { appDisplay: "MainMenu" } type ActionType = { type: "DisplayMenu" | "DisplayGame" ...

Ways to classify the prop type of a functional component by specifying the different types of props for the FC

I have created two functional components that require different prop types. export interface OrderImageProps { orders: ICartItem[] } const OrderImage: React.FC<OrderImageProps> = (props: OrderImageProps) => { return ( <div> ...

Having some trouble while attempting to set up the next-auth@beta package due to an error

Currently encountering the following error message: code EUNSUPPORTEDPROTOCOL Unsupported URL Type "workspace:": workspace:* I have made sure to update my node to the most recent recommended version. In a previous project, I successfully instal ...

Utilizing ResolveComponentFactory() with a String Key: A Step-by-Step Guide

My goal: I want to find a way to use something similar to the "resolveComponentFactory()", but with a 'string' identifier to obtain Component Factories. Once I have them, I plan to utilize the "createComponent(Factory)" method. Check out this P ...

Can Angular ping local addresses in a manner similar to using the terminal?

Looking for a way to ping devices on my local network, similar to using the ping command in the terminal to ping the router or any connected devices. I've figured out how to ping servers like google.com, but it doesn't seem to work with local add ...

Leveraging several unique Angular custom builders

For a while now, I've utilized the ng-cli-hooks custom builder to incorporate CSP into the index.html file and create a unique webpack config. Currently, I'm exploring the features of @ngx-env/builder to enable environment variables injection du ...

Avoiding page reload when utilizing the nebular menu-bar item's 'url' attribute

I have implemented the nebular theme in my application, with a menu containing two items that can be navigated using the URL attribute of the nebular menu. ISSUE: While the navigation works correctly, a page refresh occurs every time an item is clicked. ...

Creating a personalized React date selection tool using TypeScript

After following the instructions in the documentation for creating a custom datepicker, I finally managed to build one. However, I encountered an error stating "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean ...

Utilizing a Mocking/Spying Tool in Angular Unit Testing

I have a file named myHelpers.ts which contains multiple functions: myHelpers.ts export function multiply(a, b) { return a * b; } export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; } The above file al ...

How can you activate or deactivate Bootstrap Checkboxes using buttons in Angular 9?

I've been working on developing a page in Angular, although I'm still getting the hang of it. Despite spending several hours and going through numerous threads trying to find a solution, I haven't been able to address my specific issue. Jus ...

The button fails to log any text to the developer console

Attempting to verify the functionality of my button by logging a message on the developer console. However, upon clicking the button, the text does not appear in the console. import { Component, EventEmitter, Input, Output } from '@angular/core'; ...

Encountering an Error with PrimeNG dataTable when Using a p-checkbox within a p-column

My Datatable is currently functioning properly: <p-dataTable [value]="myObjects" [rows]="10" [paginator]="true" [pageLinks]="3"> <p-column field="name" header="Name"></p-column> <p-column field="size" header="Size"></p-c ...

Leveraging Angular for Parsing JSON Data

I have a JSON object that I want to use in my code. The goal is to assign the values of certain properties from the JSON object to four variables in my Angular project. These variables are named as follows: authorText : string; titleText : string; duratio ...

Typescript: Subscribed information mysteriously disappeared

[ Voting to avoid putting everything inside ngOnit because I need to reuse the API response and model array in multiple functions. Need a way to reuse without cluttering up ngOnInit. I could simply call subscribe repeatedly in each function to solve the p ...